Re: psycopg3 and adaptation choices

From: Daniele Varrazzo <daniele(dot)varrazzo(at)gmail(dot)com>
To: Vladimir Ryabtsev <greatvovan(at)gmail(dot)com>
Cc: Federico Di Gregorio <fog(at)dndg(dot)it>, psycopg(at)lists(dot)postgresql(dot)org
Subject: Re: psycopg3 and adaptation choices
Date: 2020-11-10 03:20:51
Message-ID: CA+mi_8aRQBG+Lz12oW0Be62RSR7UEEoev5Yn34ZSygcOgxbOCw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: psycopg

On Tue, 10 Nov 2020 at 01:06, Vladimir Ryabtsev <greatvovan(at)gmail(dot)com> wrote:

> May I ask you again about using 'unknown' for numbers? Could you recap
> all the downsides of this approach?

After this useful conversation, I've updated the article
(https://www.varrazzo.com/blog/2020/11/07/psycopg3-adaptation/) and
I've added comparison tables with the choices available. The integer
one is the following:

Choices to cast Python ``int`` type:

To ``unknown``:

* +1: can express the full range of the unbounded Python ``int``
* +2: can be passed without cast to most data types and functions
* -2: it round-trips back to string, error on PostgreSQL < 10

To ``numeric``:

* +1: can express the full range of the unbounded Python ``int``
* +1: can be passed without cast to most data types
* -1: requires a cast for some functions
* DELETED [-1: it round-trips to 'Decimal'`]
* +0.5: **it can round-trip back to int**, with additional care - more to
follow

To ``int8``:

* -0.5: can't express values not fitting in 64 bits (relatively limited
use case: if the target column is ``numeric`` then it would be wise for
the user to pass a ``Decimal``)
* +1: can be passed without cast to most data types
* -1: requires a cast for some functions
* +1: it round-trips back to ``int``

To ``int4``:

* -1: limited range: couldn't be used to pass a value not fitting into 32
bytes from Python to a ``bigint``.
* +2: can be passed without cast to most data types and functions
* +1: it round-trips back to ``int``

What about the DELETED entry on ``numeric``? If we dump ``int`` -> ``numeric``
to the db, and load back ``numeric`` -> ``Decimal`` from it, we end up with
integers round-tripping to ``Decimal``, which could easily create errors in
Python contexts which are not ready to deal with fixed-point arithmetic.
However, upon receiving a ``numeric`` from the database, we can check what
number it is: if it has no decimal digit it can be returned to Python as
``int``, if it has any decimal digit it must be returned as ``Decimal``.

This mechanism can be as trivial as `looking if there is a '.'`__ in the data
returned by the database; however in many cases the is job made simpler (or at
least more efficient) by the presence of the ``numeric`` modifiers:
``numeric`` comes in three flavours:

- ``numeric``: arbitrary precision (number of digits) and scale (number of
digits after the decimal point),

- ``numeric(n)``: limited precision, no digit after the decimal
point (equivalent to ``numeric(n, 0)``),

- ``numeric(n, m)``: limited precision, fixed number of
digits after the decimal point.

.. __: https://github.com/psycopg/psycopg3/commit/5ced659f4838cf72c1981518ae2804942ebbd07b

The modifier information is returned in many contexts (among which the most
important: selecting data from tables): if we know the scale `we can decide
upfront`__ to load the entire column as ``int`` if the scale is 0, ``Decimal``
otherwise. If the modifier is unknown we can look at the presence of the dot.

.. __: https://github.com/psycopg/psycopg3/commit/a9444144f7d0581284ccab198ad0355436e6822a

Returning an ``int`` in a context where ``Decimal`` are expected doesn't seem
a big problem: throwing an integer to a fixed-point calculation doesn't wreak
havoc has it does throwing a ``Decimal`` in a context of ``flaot``
calculations. Running the entire Django test suite after this change caused no
test to fail, which gives me some comfort.

In response to

Responses

Browse psycopg by date

  From Date Subject
Next Message Christophe Pettus 2020-11-10 03:22:19 Re: psycopg3 and adaptation choices
Previous Message Christophe Pettus 2020-11-10 03:20:11 Re: psycopg3 and adaptation choices