Skip to content

Commit

Permalink
1127 Fix bug with large integers in SQLite (#1128)
Browse files Browse the repository at this point in the history
* fix large integers in SQLite

* make test sqlite only

* fix integration tests (`httpx` removed `app` argument)

* use `Decimal`
  • Loading branch information
dantownsend authored Jan 7, 2025
1 parent 7373a84 commit 965c5b3
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
16 changes: 14 additions & 2 deletions piccolo/engine/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,21 @@ def convert_numeric_out(value: str) -> Decimal:
@decode_to_string
def convert_int_out(value: str) -> int:
"""
Make sure Integer values are actually of type int.
Make sure INTEGER values are actually of type ``int``.
SQLite doesn't enforce that the values in INTEGER columns are actually
integers - they could be strings ('hello'), or floats (1.0).
There's not much we can do if the value is something like 'hello' - a
``ValueError`` is appropriate in this situation.
For a value like ``1.0``, it seems reasonable to handle this, and return a
value of ``1``.
"""
return int(float(value))
# We used to use int(float(value)), but it was incorrect, because float has
# limited precision for large numbers.
return int(Decimal(value))


@decode_to_string
Expand Down
2 changes: 1 addition & 1 deletion requirements/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
coveralls==3.3.1
httpx==0.27.2
httpx==0.28.0
pytest-cov==3.0.0
pytest==6.2.5
python-dateutil==2.8.2
Expand Down
4 changes: 2 additions & 2 deletions tests/apps/asgi/commands/files/dummy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
import typing as t

from httpx import AsyncClient
from httpx import ASGITransport, AsyncClient


async def dummy_server(app: t.Union[str, t.Callable] = "app:app"):
Expand All @@ -24,7 +24,7 @@ async def dummy_server(app: t.Union[str, t.Callable] = "app:app"):
module = importlib.import_module(path)
app = t.cast(t.Callable, getattr(module, app_name))

async with AsyncClient(app=app) as client:
async with AsyncClient(transport=ASGITransport(app=app)) as client:
response = await client.get("http://localhost:8000")
if response.status_code != 200:
sys.exit("The app isn't callable!")
Expand Down
32 changes: 32 additions & 0 deletions tests/columns/test_integer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from piccolo.columns.column_types import Integer
from piccolo.table import Table
from piccolo.testing.test_case import AsyncTableTest
from tests.base import sqlite_only


class MyTable(Table):
integer = Integer()


@sqlite_only
class TestInteger(AsyncTableTest):
tables = [MyTable]

async def test_large_integer(self):
"""
Make sure large integers can be inserted and retrieved correctly.
There was a bug with this in SQLite:
https://github.com/piccolo-orm/piccolo/issues/1127
"""
integer = 625757527765811240

row = MyTable(integer=integer)
await row.save()

_row = MyTable.objects().first().run_sync()
assert _row is not None

self.assertEqual(_row.integer, integer)

0 comments on commit 965c5b3

Please sign in to comment.