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

1127 Fix bug with large integers in SQLite #1128

Merged
merged 4 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Loading