diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2021-11-18 16:16:01 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2021-11-18 16:16:01 +0000 |
commit | 9141b6c15eac4827f0df2e3f87f331c821d13b5a (patch) | |
tree | 6f79ccdc19e9b80047496d86b404794e9e7525c0 /lib | |
parent | 5b6393fb7b4282da0301eb88da5b7f33a8614d3e (diff) | |
parent | 93fad8fb0c5421ad162064e0aa506cb1e70cbf2b (diff) | |
download | sqlalchemy-9141b6c15eac4827f0df2e3f87f331c821d13b5a.tar.gz |
Merge "remove "native decimal" warning" into main
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqlalchemy/sql/sqltypes.py | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/requirements.py | 15 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/suite/test_types.py | 33 |
3 files changed, 38 insertions, 20 deletions
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 559946072..52033f586 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -490,16 +490,6 @@ class Numeric(_LookupExpressionAdapter, TypeEngine): # we're a "numeric", DBAPI will give us Decimal directly return None else: - util.warn( - "Dialect %s+%s does *not* support Decimal " - "objects natively, and SQLAlchemy must " - "convert from floating point - rounding " - "errors and other issues may occur. Please " - "consider storing Decimal numbers as strings " - "or integers on this platform for lossless " - "storage." % (dialect.name, dialect.driver) - ) - # we're a "numeric", DBAPI returns floats, convert. return processors.to_decimal_processor_factory( decimal.Decimal, diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 4cc431bb7..56df452a5 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -957,6 +957,21 @@ class SuiteRequirements(Requirements): return exclusions.open() @property + def numeric_received_as_decimal_untyped(self): + """target backend will return result columns that are explicitly + against NUMERIC or similar precision-numeric datatypes (not including + FLOAT or INT types) as Python Decimal objects, and not as floats + or ints, including when no SQLAlchemy-side typing information is + associated with the statement (e.g. such as a raw SQL string). + + This should be enabled if either the DBAPI itself returns Decimal + objects, or if the dialect has set up DBAPI-specific return type + handlers such that Decimal objects come back automatically. + + """ + return exclusions.open() + + @property def nested_aggregates(self): """target database can select an aggregate from a subquery that's also using an aggregate diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 7438b8bc8..aa796df76 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -35,6 +35,7 @@ from ... import testing from ... import Text from ... import Time from ... import TIMESTAMP +from ... import type_coerce from ... import TypeDecorator from ... import Unicode from ... import UnicodeText @@ -524,9 +525,6 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): @testing.fixture def do_numeric_test(self, metadata, connection): - @testing.emits_warning( - r".*does \*not\* support Decimal objects natively" - ) def run(type_, input_, output, filter_=None, check_scale=False): t = Table("t", metadata, Column("x", type_)) t.create(connection) @@ -541,9 +539,30 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): if check_scale: eq_([str(x) for x in result], [str(x) for x in output]) + connection.execute(t.delete()) + + # test that this is actually a number! + # note we have tiny scale here as we have tests with very + # small scale Numeric types. PostgreSQL will raise an error + # if you use values outside the available scale. + if type_.asdecimal: + test_value = decimal.Decimal("2.9") + add_value = decimal.Decimal("37.12") + else: + test_value = 2.9 + add_value = 37.12 + + connection.execute(t.insert(), {"x": test_value}) + assert_we_are_a_number = connection.scalar( + select(type_coerce(t.c.x + add_value, type_)) + ) + eq_( + round(assert_we_are_a_number, 3), + round(test_value + add_value, 3), + ) + return run - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_render_literal_numeric(self, literal_round_trip): literal_round_trip( Numeric(precision=8, scale=4), @@ -551,7 +570,6 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): [decimal.Decimal("15.7563")], ) - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_render_literal_numeric_asfloat(self, literal_round_trip): literal_round_trip( Numeric(precision=8, scale=4, asdecimal=False), @@ -637,14 +655,12 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): # to render CAST unconditionally since this is kind of an edge case. @testing.requires.implicit_decimal_binds - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_decimal_coerce_round_trip(self, connection): expr = decimal.Decimal("15.7563") val = connection.scalar(select(literal(expr))) eq_(val, expr) - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_decimal_coerce_round_trip_w_cast(self, connection): expr = decimal.Decimal("15.7563") @@ -984,7 +1000,6 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): return datatype, compare_value, p_s @_index_fixtures(False) - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_index_typed_access(self, datatype, value): data_table = self.tables.data_table data_element = {"key1": value} @@ -1007,7 +1022,6 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): is_(type(roundtrip), type(compare_value)) @_index_fixtures(True) - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_index_typed_comparison(self, datatype, value): data_table = self.tables.data_table data_element = {"key1": value} @@ -1032,7 +1046,6 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): eq_(row, (compare_value,)) @_index_fixtures(True) - @testing.emits_warning(r".*does \*not\* support Decimal objects natively") def test_path_typed_comparison(self, datatype, value): data_table = self.tables.data_table data_element = {"key1": {"subkey1": value}} |