Skip to content

Implement binary format codec for numeric type #168

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

Merged
merged 1 commit into from
Jul 6, 2017
Merged

Conversation

elprans
Copy link
Member

@elprans elprans commented Jul 6, 2017

Fixes: #157

@elprans elprans requested a review from 1st1 July 6, 2017 17:58
@elprans elprans force-pushed the numeric-binary branch 2 times, most recently from 83f69af to 6b6d554 Compare July 6, 2017 18:08
"SELECT $1::numeric", decimal.Decimal('NaN'))
self.assertTrue(res.is_nan())

with self.assertRaisesRegex(ValueError, 'numeric type does not '
Copy link
Member

@1st1 1st1 Jul 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python also supports signalling NaN (sNaN) -- add a check that we handle it with a proper exception. Or maybe we should convert Python's sNaN to pg NaN.

Copy link
Member

@1st1 1st1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than a sNaN thing, lgtm.

@sergeyspatar
Copy link

I tested this version on a bunch of different values and tests passed:

import asyncpg
import asyncio

#import uvloop
#asyncio.set_event_loop(uvloop.new_event_loop())

loop = asyncio.get_event_loop()

from decimal import Decimal

async def run(value):
    conn = await asyncpg.connect(user='postgres')
    await conn.execute('create temporary table temp_table (c1 numeric(6,3))')
    await conn.copy_records_to_table('temp_table', records=[(value,)])
    return await conn.fetchrow('select c1 from temp_table')

for value in [123, -999, 0.123, -999.999, Decimal('0.123'), Decimal('-0.001'), Decimal('-0.0009'), None]:
    print('Testing:', repr(value))
    row = loop.run_until_complete(run(value))
    print('Result:', repr(row[0]))
    print()

Output:

Testing: 123
Result: Decimal('123')

Testing: -999
Result: Decimal('-999')

Testing: 0.123
Result: Decimal('0.1230')

Testing: -999.999
Result: Decimal('-999.9990')

Testing: Decimal('0.123')
Result: Decimal('0.1230')

Testing: Decimal('-0.001')
Result: Decimal('-0.0010')

Testing: Decimal('-0.0009')
Result: Decimal('-0.0010')

Testing: None
Result: None

The only thing I noticed is that when selecting column back from table returned Decimal value has higher precision than in column type (4 vs. 3 digits after decimal point in my tests). For example, Decimal('0.123') saved as numeric(6,3) and then queried became Decimal('0.1230').

@elprans
Copy link
Member Author

elprans commented Jul 6, 2017

The only thing I noticed is that when selecting column back from table returned Decimal value has higher precision than in column type (4 vs. 3 digits after decimal point in my tests). For example, Decimal('0.123') saved as numeric(6,3) and then queried became Decimal('0.1230').

Thanks for catching this. I pushed an updated version that fixes this.

@sergeyspatar
Copy link

I pushed an updated version that fixes this.

Thank you Elvis! I retested and now fetched Decimal precision is correct.

@elprans elprans merged commit a5413eb into master Jul 6, 2017
@elprans elprans deleted the numeric-binary branch July 6, 2017 20:54
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

Successfully merging this pull request may close these issues.

3 participants