Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Incorrect serialization of numeric values #1113

Open
Ragueel opened this issue Jan 4, 2024 · 2 comments
Open

bug: Incorrect serialization of numeric values #1113

Ragueel opened this issue Jan 4, 2024 · 2 comments

Comments

@Ragueel
Copy link

Ragueel commented Jan 4, 2024

  • asyncpg version: 0.29.0
  • PostgreSQL version: 13
  • Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
    the issue with a local PostgreSQL install?
    : no SaaS, yes reproducable with local postgres
  • Python version: 3.10
  • Platform: linux
  • Do you use pgbouncer?: no
  • Did you install asyncpg with pip?: yes
  • If you built asyncpg locally, which version of Cython did you use?: none
  • Can the issue be reproduced under both asyncio and
    uvloop?
    : yes

This happens when query selects a numeric column. Numbers like 10000, 100000, etc. get serialized in scientific notation. For example 10000 becomes 1E+4.

To reproduce the error, you can do the following:

Inside tests/test_codecs/test_numeric if 10000 is added in cases then the test fails, due to incorrect serialization logic.

    async def test_numeric(self):
        # Test that we handle dscale correctly.
        cases = [
            '0.001',
            '0.001000',
            '1',
            '1.00000',
            '10000', # new test case
        ]

fail error:

line 614, in test_numeric
    self.assertEqual(str(res), case)
AssertionError: '1E+4' != '10000'
@elprans
Copy link
Member

elprans commented Jan 4, 2024

Technically there is no asyncpg bug here, because 1E+4 == 10000, it's just a different representation of the same decimal.Decimal value. If you need a different string representation, use explicit formatting, e.g. print(f'{value:f}')

@Ragueel
Copy link
Author

Ragueel commented Jan 5, 2024

Technically there is no asyncpg bug here, because 1E+4 == 10000, it's just a different representation of the same decimal.Decimal value. If you need a different string representation, use explicit formatting, e.g. print(f'{value:f}')

I don't think using scientific notation by default is a correct behaviour. Consider the following code:

a = Decimal('100000')
b = Decimal('1E+5')

str(a) == str(b) # will be false

This might cause some strange errors, when this value would be used. I encoutered this error when I was dumping data to json, and was surpised on why it was using scientific notation for numbers in the power of 10.

It is also not documented anywhere that this behaviour would be used for numeric values, and users should handle it by themselves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants