From: Federico Caselli Date: Wed, 6 Sep 2023 20:18:29 +0000 (+0200) Subject: Clarify what float are compiled to X-Git-Tag: rel_2_0_21~19^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=92ee0326d64305e95f70d9c9b06bf9d193dae960;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Clarify what float are compiled to Change-Id: I8b1c083ae7ccf803a94401f57a00d058a8ce7aae References: #10300 --- diff --git a/doc/build/dialects/postgresql.rst b/doc/build/dialects/postgresql.rst index 3e981f04aa..0575837185 100644 --- a/doc/build/dialects/postgresql.rst +++ b/doc/build/dialects/postgresql.rst @@ -363,37 +363,45 @@ they originate from :mod:`sqlalchemy.types` or from the local dialect:: CIDR, CITEXT, DATE, + DATEMULTIRANGE, + DATERANGE, + DOMAIN, DOUBLE_PRECISION, ENUM, FLOAT, HSTORE, INET, + INT4MULTIRANGE, + INT4RANGE, + INT8MULTIRANGE, + INT8RANGE, INTEGER, INTERVAL, JSON, JSONB, + JSONPATH, MACADDR, MACADDR8, MONEY, NUMERIC, + NUMMULTIRANGE, + NUMRANGE, OID, REAL, + REGCLASS, + REGCONFIG, SMALLINT, TEXT, TIME, TIMESTAMP, - UUID, - VARCHAR, - INT4RANGE, - INT8RANGE, - NUMRANGE, - DATERANGE, + TSMULTIRANGE, + TSQUERY, TSRANGE, + TSTZMULTIRANGE, TSTZRANGE, - REGCONFIG, - REGCLASS, - TSQUERY, TSVECTOR, + UUID, + VARCHAR, ) Types which are specific to PostgreSQL, or have PostgreSQL-specific diff --git a/lib/sqlalchemy/dialects/oracle/__init__.py b/lib/sqlalchemy/dialects/oracle/__init__.py index 71aacd4059..46a5d0a205 100644 --- a/lib/sqlalchemy/dialects/oracle/__init__.py +++ b/lib/sqlalchemy/dialects/oracle/__init__.py @@ -59,4 +59,5 @@ __all__ = ( "VARCHAR2", "NVARCHAR2", "ROWID", + "REAL", ) diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index fe6386f22e..da7f7300bc 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -608,14 +608,21 @@ class Numeric(HasExpressionLookup, TypeEngine[_N]): class Float(Numeric[_N]): - """Type representing floating point types, such as ``FLOAT`` or ``REAL``. This type returns Python ``float`` objects by default, unless the - :paramref:`.Float.asdecimal` flag is set to True, in which case they + :paramref:`.Float.asdecimal` flag is set to ``True``, in which case they are coerced to ``decimal.Decimal`` objects. - + When a :paramref:`.Float.precision` is not provided in a + :class:`_types.Float` type some backend may compile this type as + an 8 bytes / 64 bit float datatype. To use a 4 bytes / 32 bit float + datatype a precision <= 24 can usually be provided or the + :class:`_types.REAL` type can be used. + This is known to be the case in the PostgreSQL and MSSQL dialects + that render the type as ``FLOAT`` that's in both an alias of + ``DOUBLE PRECISION``. Other third party dialects may have similar + behavior. """ __visit_name__ = "float" diff --git a/test/dialect/mssql/test_types.py b/test/dialect/mssql/test_types.py index 2939c097c3..a225dde532 100644 --- a/test/dialect/mssql/test_types.py +++ b/test/dialect/mssql/test_types.py @@ -1627,3 +1627,22 @@ class BooleanTest(fixtures.TestBase, AssertsCompiledSQL): ddl, ) assert isinstance(tbl.c.boo.type.as_generic(), Boolean) + + +class NumberTest(fixtures.TestBase, AssertsCompiledSQL): + __dialect__ = mssql.dialect() + + @testing.combinations( + ("sa", sqltypes.Float(), "FLOAT"), # ideally it should render real + ("sa", sqltypes.Double(), "DOUBLE PRECISION"), + ("sa", sqltypes.FLOAT(), "FLOAT"), + ("sa", sqltypes.REAL(), "REAL"), + ("sa", sqltypes.DOUBLE(), "DOUBLE"), + ("sa", sqltypes.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("mssql", mssql.FLOAT(), "FLOAT"), + ("mssql", mssql.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("mssql", mssql.REAL(), "REAL"), + id_="ira", + ) + def test_float_type_compile(self, type_, sql_text): + self.assert_compile(type_, sql_text) diff --git a/test/dialect/mysql/test_types.py b/test/dialect/mysql/test_types.py index af68a24c5a..1d279e720d 100644 --- a/test/dialect/mysql/test_types.py +++ b/test/dialect/mysql/test_types.py @@ -462,6 +462,21 @@ class TypeCompileTest(fixtures.TestBase, AssertsCompiledSQL): datetime.time(8, 37, 35, 450), ) + @testing.combinations( + ("sa", sqltypes.Float(), "FLOAT"), + ("sa", sqltypes.Double(), "DOUBLE"), + ("sa", sqltypes.FLOAT(), "FLOAT"), + ("sa", sqltypes.REAL(), "REAL"), + ("sa", sqltypes.DOUBLE(), "DOUBLE"), + ("sa", sqltypes.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("mysql", mysql.FLOAT(), "FLOAT"), + ("mysql", mysql.DOUBLE(), "DOUBLE"), + ("mysql", mysql.REAL(), "REAL"), + id_="ira", + ) + def test_float_type_compile(self, type_, sql_text): + self.assert_compile(type_, sql_text) + class TypeRoundTripTest(fixtures.TestBase, AssertsExecutionResults): __dialect__ = mysql.dialect() diff --git a/test/dialect/oracle/test_types.py b/test/dialect/oracle/test_types.py index 55fe368656..a970adc4ba 100644 --- a/test/dialect/oracle/test_types.py +++ b/test/dialect/oracle/test_types.py @@ -191,6 +191,23 @@ class DialectTypesTest(fixtures.TestBase, AssertsCompiledSQL): expr = column("bar", oracle.INTERVAL) == datetime.timedelta(days=1) eq_(expr.right.type._type_affinity, sqltypes.Interval) + @testing.combinations( + ("sa", sqltypes.Float(), "FLOAT"), + ("sa", sqltypes.Double(), "DOUBLE PRECISION"), + ("sa", sqltypes.FLOAT(), "FLOAT"), + ("sa", sqltypes.REAL(), "REAL"), + ("sa", sqltypes.DOUBLE(), "DOUBLE"), + ("sa", sqltypes.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("oracle", oracle.FLOAT(), "FLOAT"), + ("oracle", oracle.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("oracle", oracle.REAL(), "REAL"), + ("oracle", oracle.BINARY_DOUBLE(), "BINARY_DOUBLE"), + ("oracle", oracle.BINARY_FLOAT(), "BINARY_FLOAT"), + id_="ira", + ) + def test_float_type_compile(self, type_, sql_text): + self.assert_compile(type_, sql_text) + class TypesTest(fixtures.TestBase): __only_on__ = "oracle" diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 422e735d3d..73a66fff61 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -99,6 +99,8 @@ from ...engine.test_ddlevents import DDLEventWCreateHarness class MiscTypesTest(AssertsCompiledSQL, fixtures.TestBase): + __dialect__ = postgresql.dialect() + @testing.combinations( ("asyncpg", "x LIKE $1::VARCHAR"), ("psycopg", "x LIKE %(x_1)s::VARCHAR"), @@ -119,6 +121,21 @@ class MiscTypesTest(AssertsCompiledSQL, fixtures.TestBase): dialect=f"postgresql+{driver}", ) + @testing.combinations( + ("sa", sqltypes.Float(), "FLOAT"), # ideally it should render real + ("sa", sqltypes.Double(), "DOUBLE PRECISION"), + ("sa", sqltypes.FLOAT(), "FLOAT"), + ("sa", sqltypes.REAL(), "REAL"), + ("sa", sqltypes.DOUBLE(), "DOUBLE"), + ("sa", sqltypes.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("pg", postgresql.FLOAT(), "FLOAT"), + ("pg", postgresql.DOUBLE_PRECISION(), "DOUBLE PRECISION"), + ("pg", postgresql.REAL(), "REAL"), + id_="ira", + ) + def test_float_type_compile(self, type_, sql_text): + self.assert_compile(type_, sql_text) + class FloatCoercionTest(fixtures.TablesTest, AssertsExecutionResults): __only_on__ = "postgresql"