summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2021-11-18 16:16:01 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2021-11-18 16:16:01 +0000
commit9141b6c15eac4827f0df2e3f87f331c821d13b5a (patch)
tree6f79ccdc19e9b80047496d86b404794e9e7525c0 /lib
parent5b6393fb7b4282da0301eb88da5b7f33a8614d3e (diff)
parent93fad8fb0c5421ad162064e0aa506cb1e70cbf2b (diff)
downloadsqlalchemy-9141b6c15eac4827f0df2e3f87f331c821d13b5a.tar.gz
Merge "remove "native decimal" warning" into main
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/sql/sqltypes.py10
-rw-r--r--lib/sqlalchemy/testing/requirements.py15
-rw-r--r--lib/sqlalchemy/testing/suite/test_types.py33
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}}