]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
fixes: 5465
authorzeeeeeb <5767468+zeeeeeb@users.noreply.github.com>
Tue, 8 Feb 2022 05:37:45 +0000 (21:37 -0800)
committerzeeeeeb <5767468+zeeeeeb@users.noreply.github.com>
Tue, 8 Feb 2022 05:37:45 +0000 (21:37 -0800)
20 files changed:
doc/build/changelog/unreleased_14/5465.rst [new file with mode: 0644]
doc/build/core/type_basics.rst
lib/sqlalchemy/__init__.py
lib/sqlalchemy/dialects/mssql/base.py
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/mysql/types.py
lib/sqlalchemy/dialects/oracle/base.py
lib/sqlalchemy/dialects/postgresql/base.py
lib/sqlalchemy/dialects/sqlite/base.py
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/sqltypes.py
lib/sqlalchemy/types.py
test/dialect/mssql/test_types.py
test/dialect/mysql/test_compiler.py
test/dialect/oracle/test_compiler.py
test/dialect/oracle/test_reflection.py
test/dialect/oracle/test_types.py
test/dialect/postgresql/test_compiler.py
test/dialect/postgresql/test_types.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_14/5465.rst b/doc/build/changelog/unreleased_14/5465.rst
new file mode 100644 (file)
index 0000000..af839df
--- /dev/null
@@ -0,0 +1,6 @@
+.. change::
+    :tags: datatypes, use case
+    :tickets: 5465
+
+    Implements generic Double, DOUBLE types with compiler mapping to 
+    respective DOUBLE/DOUBLE PRECISION/FLOAT types in Dialects. 
index 3ec50cc003917cfc4e930a2f263fb52f54a66ced..a3d8cb8a5773887526c6de42c991bafd74be5c99 100644 (file)
@@ -52,6 +52,9 @@ type is emitted in ``CREATE TABLE``, such as ``VARCHAR`` see
 .. autoclass:: Enum
   :members: __init__, create, drop
 
+.. autoclass:: Double
+   :members:
+
 .. autoclass:: Float
   :members:
 
index 7d402d44eceba69302eb08382016f1206fa7aa7c..ab67d09a1199920ea732cd20619105da565ec0aa 100644 (file)
@@ -98,6 +98,8 @@ from .types import Date as Date
 from .types import DATETIME as DATETIME
 from .types import DateTime as DateTime
 from .types import DECIMAL as DECIMAL
+from .types import DOUBLE
+from .types import Double
 from .types import Enum as Enum
 from .types import FLOAT as FLOAT
 from .types import Float as Float
index 2aff7d8b6df9c65ef4d3aaaf521a488acf80f46d..6b01960d459d355ecb336c10212fd4bfde0db141 100644 (file)
@@ -1488,6 +1488,9 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
         else:
             return "FLOAT(%(precision)s)" % {"precision": precision}
 
+    def visit_DOUBLE(self, type_, **kw):
+        return "FLOAT"
+
     def visit_TINYINT(self, type_, **kw):
         return "TINYINT"
 
index 7ec2b3dc2647747d563d82b326ce79563de1ca81..5c2de091154c8acddff4900a10aa21b823f39f43 100644 (file)
@@ -1082,6 +1082,7 @@ colspecs = {
     _FloatType: _FloatType,
     sqltypes.Numeric: NUMERIC,
     sqltypes.Float: FLOAT,
+    sqltypes.Double: DOUBLE,
     sqltypes.Time: TIME,
     sqltypes.Enum: ENUM,
     sqltypes.MatchType: _MatchType,
index 855fac1b367c2df68582d5a9d9c3a3c62f67b0b9..2a4b4ad5fbe23c92e57aa2679e521d5149f90195 100644 (file)
@@ -152,7 +152,7 @@ class DECIMAL(_NumericType, sqltypes.DECIMAL):
         )
 
 
-class DOUBLE(_FloatType):
+class DOUBLE(_FloatType, sqltypes.DOUBLE):
     """MySQL DOUBLE type."""
 
     __visit_name__ = "DOUBLE"
index 578450d248f1f7bbe2ce3dd048c64bab30ca4589..c10f83cfac490325f9a97d95415b41e463edcf54 100644 (file)
@@ -625,7 +625,7 @@ class NUMBER(sqltypes.Numeric, sqltypes.Integer):
             return sqltypes.Integer
 
 
-class DOUBLE_PRECISION(sqltypes.Float):
+class DOUBLE_PRECISION(sqltypes.Double):
     __visit_name__ = "DOUBLE_PRECISION"
 
 
@@ -760,12 +760,18 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler):
     def visit_float(self, type_, **kw):
         return self.visit_FLOAT(type_, **kw)
 
+    def visit_double(self, type_, **kw):
+        return self.visit_DOUBLE_PRECISION(type_, **kw)
+
     def visit_unicode(self, type_, **kw):
         if self.dialect._use_nchar_for_unicode:
             return self.visit_NVARCHAR2(type_, **kw)
         else:
             return self.visit_VARCHAR2(type_, **kw)
 
+    def visit_DOUBLE(self, type_, **kw):
+        return self.visit_DOUBLE_PRECISION(type_, **kw)
+
     def visit_INTERVAL(self, type_, **kw):
         return "INTERVAL DAY%s TO SECOND%s" % (
             type_.day_precision is not None
index 698ea277f5d2c21efc99673759fa1d58f1550c55..2d44932c0fdcca1772e7d06eba1167de64b66f1c 100644 (file)
@@ -1575,7 +1575,7 @@ class BYTEA(sqltypes.LargeBinary):
     __visit_name__ = "BYTEA"
 
 
-class DOUBLE_PRECISION(sqltypes.Float):
+class DOUBLE_PRECISION(sqltypes.Double):
     __visit_name__ = "DOUBLE_PRECISION"
 
 
@@ -2899,6 +2899,12 @@ class PGTypeCompiler(compiler.GenericTypeCompiler):
     def visit_DOUBLE_PRECISION(self, type_, **kw):
         return "DOUBLE PRECISION"
 
+    def visit_DOUBLE(self, type_, **kw):
+        return "DOUBLE PRECISION"
+
+    def visit_double(self, type_, **kw):
+        return "DOUBLE PRECISION"
+
     def visit_BIGINT(self, type_, **kw):
         return "BIGINT"
 
index 236f6eaeff85f72a142485e02171642e3b00b2cd..246602155a83617b5336997682e4f43a93f47381 100644 (file)
@@ -1179,7 +1179,7 @@ ischema_names = {
     "DATE_CHAR": sqltypes.DATE,
     "DATETIME": sqltypes.DATETIME,
     "DATETIME_CHAR": sqltypes.DATETIME,
-    "DOUBLE": sqltypes.FLOAT,
+    "DOUBLE": sqltypes.DOUBLE,
     "DECIMAL": sqltypes.DECIMAL,
     "FLOAT": sqltypes.FLOAT,
     "INT": sqltypes.INTEGER,
index 8a3f264255f26bbb06f232948db2cb8b69343690..1b0bc69c606b635fdff8b300ae207f64a308cc41 100644 (file)
@@ -4848,6 +4848,9 @@ class GenericTypeCompiler(TypeCompiler):
     def visit_FLOAT(self, type_, **kw):
         return "FLOAT"
 
+    def visit_DOUBLE(self, type_, **kw):
+        return "DOUBLE"
+
     def visit_REAL(self, type_, **kw):
         return "REAL"
 
@@ -4966,6 +4969,9 @@ class GenericTypeCompiler(TypeCompiler):
     def visit_float(self, type_, **kw):
         return self.visit_FLOAT(type_, **kw)
 
+    def visit_double(self, type_, **kw):
+        return self.visit_DOUBLE(type_, **kw)
+
     def visit_numeric(self, type_, **kw):
         return self.visit_NUMERIC(type_, **kw)
 
index 42fad5e0443a4c2b3be2d69b0022586b2f40d9f3..1b430bed8bcc849d426a1b05135f307daaaf5030 100644 (file)
@@ -600,6 +600,17 @@ class Float(Numeric):
             return None
 
 
+class Double(Float):
+    """A type for double ``FLOAT`` floating point types.
+
+    Typically generates a ``DOUBLE`` or ``DOUBLE_PRECISION`` in DDL,
+    and otherwise acts like a normal :class:`.Float` on the Python
+    side.
+    """
+
+    __visit_name__ = "double"
+
+
 class DateTime(_LookupExpressionAdapter, TypeEngine[dt.datetime]):
 
     """A type for ``datetime.datetime()`` objects.
@@ -2766,6 +2777,13 @@ class FLOAT(Float):
     __visit_name__ = "FLOAT"
 
 
+class DOUBLE(Double):
+
+    """The SQL DOUBLE type."""
+
+    __visit_name__ = "DOUBLE"
+
+
 class NUMERIC(Numeric):
 
     """The SQL NUMERIC type."""
index 07263c5b9eec97bd22df28295ae4f668c90215e7..a0e0118bdd175afd964fd9c6e1182595037d79df 100644 (file)
@@ -22,6 +22,7 @@ __all__ = [
     "TEXT",
     "Text",
     "FLOAT",
+    "DOUBLE",
     "NUMERIC",
     "REAL",
     "DECIMAL",
@@ -44,6 +45,7 @@ __all__ = [
     "BigInteger",
     "Numeric",
     "Float",
+    "Double",
     "DateTime",
     "Date",
     "Time",
@@ -76,6 +78,8 @@ from .sql.sqltypes import Date
 from .sql.sqltypes import DATETIME
 from .sql.sqltypes import DateTime
 from .sql.sqltypes import DECIMAL
+from .sql.sqltypes import DOUBLE
+from .sql.sqltypes import Double
 from .sql.sqltypes import Enum
 from .sql.sqltypes import FLOAT
 from .sql.sqltypes import Float
index 2ef8b76daeeb3990815132e7f254e28570abdcec..ba74a7970aa5f3bbde952154cf3eb2fe23833c8f 100644 (file)
@@ -295,6 +295,8 @@ class TypeDDLTest(fixtures.TestBase):
             (types.Float, [], {}, "FLOAT"),
             (types.Float, [None], {}, "FLOAT"),
             (types.Float, [12], {}, "FLOAT(12)"),
+            (types.Double, [], {}, "FLOAT"),
+            (types.DOUBLE, [], {}, "FLOAT"),
             (mssql.MSReal, [], {}, "REAL"),
             (types.Integer, [], {}, "INTEGER"),
             (types.BigInteger, [], {}, "BIGINT"),
index ba162b49020686aad019ec99f30d7ca6cafc8ed6..fa8f37c1f83ea6a8f4db7f434b613113c14585a6 100644 (file)
@@ -15,6 +15,8 @@ from sqlalchemy import Date
 from sqlalchemy import DATETIME
 from sqlalchemy import DateTime
 from sqlalchemy import DECIMAL
+from sqlalchemy import DOUBLE
+from sqlalchemy import Double
 from sqlalchemy import exc
 from sqlalchemy import extract
 from sqlalchemy import FLOAT
@@ -776,6 +778,8 @@ class SQLTest(fixtures.TestBase, AssertsCompiledSQL):
         (Float, "t.col"),
         (m.MSFloat, "t.col"),
         (m.MSDouble, "t.col"),
+        (DOUBLE, "t.col"),
+        (Double, "t.col"),
         (m.MSReal, "t.col"),
         (m.MSYear, "t.col"),
         (m.MSYear(2), "t.col"),
@@ -798,6 +802,8 @@ class SQLTest(fixtures.TestBase, AssertsCompiledSQL):
         (m.FLOAT, "CAST(t.col AS FLOAT)"),
         (Float, "CAST(t.col AS FLOAT)"),
         (FLOAT, "CAST(t.col AS FLOAT)"),
+        (Double, "CAST(t.col AS DOUBLE)"),
+        (DOUBLE, "CAST(t.col AS DOUBLE)"),
         (m.DOUBLE, "CAST(t.col AS DOUBLE)"),
         (m.FLOAT, "CAST(t.col AS FLOAT)"),
         argnames="type_,expected",
index 22ffc888ab088e2f6ba7387c60d2735f35d7db7a..4cb6a8bb84aa313ccde3d7e73857693c07c64d55 100644 (file)
@@ -1,6 +1,7 @@
 # coding: utf-8
 from sqlalchemy import and_
 from sqlalchemy import bindparam
+from sqlalchemy import cast
 from sqlalchemy import Computed
 from sqlalchemy import exc
 from sqlalchemy import except_
@@ -23,6 +24,7 @@ from sqlalchemy import testing
 from sqlalchemy import text
 from sqlalchemy import type_coerce
 from sqlalchemy import TypeDecorator
+from sqlalchemy import types as sqltypes
 from sqlalchemy import union
 from sqlalchemy.dialects.oracle import base as oracle
 from sqlalchemy.dialects.oracle import cx_oracle
@@ -1380,6 +1382,20 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             dialect=dd,
         )
 
+    def test_double_to_oracle_double(self):
+        """test #5465:
+        test sqlalchemy Double/DOUBLE to PostgreSQL DOUBLE PRECISION
+        """
+        d1 = sqltypes.Double
+        d2 = sqltypes.DOUBLE
+
+        self.assert_compile(
+            cast(column("foo"), d1), "CAST(foo AS DOUBLE PRECISION)"
+        )
+        self.assert_compile(
+            cast(column("bar"), d2), "CAST(bar AS DOUBLE PRECISION)"
+        )
+
 
 class SequenceTest(fixtures.TestBase, AssertsCompiledSQL):
     def test_basic(self):
index df8dff30f80168a4ce29e4ccd6755b5acc1a1fdd..4c1a617610716097f648279fa525ee144a07ef5b 100644 (file)
@@ -1,6 +1,7 @@
 # coding: utf-8
 
 
+from sqlalchemy import DOUBLE
 from sqlalchemy import exc
 from sqlalchemy import FLOAT
 from sqlalchemy import ForeignKey
@@ -803,7 +804,7 @@ class TypeReflectionTest(fixtures.TestBase):
         connection,
     ):
         specs = [
-            (DOUBLE_PRECISION(), FLOAT()),
+            (DOUBLE_PRECISION(), DOUBLE()),
             # when binary_precision is supported
             # (DOUBLE_PRECISION(), oracle.FLOAT(binary_precision=126)),
             (BINARY_DOUBLE(), BINARY_DOUBLE()),
index 715a90000c16cfa597720e8f06eb936363f79601..8f478feb549cb37e158f2c8e17cb863004733820 100644 (file)
@@ -12,6 +12,8 @@ from sqlalchemy import CHAR
 from sqlalchemy import DATE
 from sqlalchemy import Date
 from sqlalchemy import DateTime
+from sqlalchemy import DOUBLE
+from sqlalchemy import Double
 from sqlalchemy import event
 from sqlalchemy import FLOAT
 from sqlalchemy import Float
@@ -309,7 +311,9 @@ class TypesTest(fixtures.TestBase):
             Column("numericcol", Numeric(precision=9, scale=2)),
             Column("floatcol1", Float()),
             Column("floatcol2", FLOAT()),
-            Column("doubleprec", oracle.DOUBLE_PRECISION),
+            Column("doubleprec1", oracle.DOUBLE_PRECISION),
+            Column("doubleprec2", Double()),
+            Column("doubleprec3", DOUBLE()),
             Column("numbercol1", oracle.NUMBER(9)),
             Column("numbercol2", oracle.NUMBER(9, 3)),
             Column("numbercol3", oracle.NUMBER),
index b98d0fac6aba53dcdb44e1a322b0f1b751efe44d..400080e78d46930d5261b98b0c91f4efc35176e1 100644 (file)
@@ -243,6 +243,21 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             "CAST(bar AS someschema.somename) AS bar",
         )
 
+    def test_cast_double_pg_double(self):
+        """test #5465:
+
+        test sqlalchemy Double/DOUBLE to PostgreSQL DOUBLE PRECISION
+        """
+        d1 = sqltypes.Double
+        d2 = sqltypes.DOUBLE
+
+        stmt = select(cast(column("foo"), d1), cast(column("bar"), d2))
+        self.assert_compile(
+            stmt,
+            "SELECT CAST(foo AS DOUBLE PRECISION) AS foo, "
+            "CAST(bar AS DOUBLE PRECISION) AS bar",
+        )
+
     def test_cast_enum_schema_translate(self):
         """test #6739"""
         e1 = Enum("x", "y", "z", name="somename")
index 0c00c76333c1164c9c3eb55293efb737433b969e..96d1f1f3e70a25049b6025b4faeaeab7e8867dff 100644 (file)
@@ -12,6 +12,7 @@ from sqlalchemy import cast
 from sqlalchemy import Column
 from sqlalchemy import column
 from sqlalchemy import DateTime
+from sqlalchemy import Double
 from sqlalchemy import Enum
 from sqlalchemy import exc
 from sqlalchemy import Float
@@ -127,6 +128,7 @@ class FloatCoercionTest(fixtures.TablesTest, AssertsExecutionResults):
             Column("x", postgresql.ARRAY(Float)),
             Column("y", postgresql.ARRAY(REAL)),
             Column("z", postgresql.ARRAY(postgresql.DOUBLE_PRECISION)),
+            Column("w", postgresql.ARRAY(Double)),
             Column("q", postgresql.ARRAY(Numeric)),
         )
         metadata.create_all(connection)
@@ -143,6 +145,7 @@ class FloatCoercionTest(fixtures.TablesTest, AssertsExecutionResults):
             Column("x", sqltypes.ARRAY(Float)),
             Column("y", sqltypes.ARRAY(REAL)),
             Column("z", sqltypes.ARRAY(postgresql.DOUBLE_PRECISION)),
+            Column("w", sqltypes.ARRAY(Double)),
             Column("q", sqltypes.ARRAY(Numeric)),
         )
         metadata.create_all(connection)
index 79b77581d0bfa2f256c4ce8b588bf5fcb2692301..e5891b2bb386945bb037d07bea9e1c3eecb577a3 100644 (file)
@@ -23,6 +23,7 @@ from sqlalchemy import DateTime
 from sqlalchemy import DECIMAL
 from sqlalchemy import dialects
 from sqlalchemy import distinct
+from sqlalchemy import Double
 from sqlalchemy import Enum
 from sqlalchemy import exc
 from sqlalchemy import FLOAT
@@ -277,6 +278,7 @@ class AdaptTest(fixtures.TestBase):
         eq_(types.Numeric(asdecimal=False).python_type, float)
         eq_(types.LargeBinary().python_type, bytes)
         eq_(types.Float().python_type, float)
+        eq_(types.Double().python_type, float)
         eq_(types.Interval().python_type, datetime.timedelta)
         eq_(types.Date().python_type, datetime.date)
         eq_(types.DateTime().python_type, datetime.datetime)
@@ -3455,6 +3457,9 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             dialects.postgresql.FLOAT(), "FLOAT", allow_dialect_select=True
         )
 
+    def test_default_compile_double(self):
+        self.assert_compile(Double(), "DOUBLE")
+
     def test_default_compile_mysql_integer(self):
         self.assert_compile(
             dialects.mysql.INTEGER(display_width=5),