-
Notifications
You must be signed in to change notification settings - Fork 91
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
SQLiteEngine not handling large Integers properly. #1127
Comments
@vertyco When precision is important, you should use Numeric (or from piccolo.columns import Serial, Numeric, Decimal
class SomeTable(Table, db=DB):
id: Serial
# Discord Guild ID
num1 = Numeric()
num2 = Decimal()
num3 = Numeric() Result is: PICCOLO
num1 625757527765811240
num2 625757527765811240
num3 625757527765811240
---
aiosqlite
num1 625757527765811240
num2 625757527765811240
num3 625757527765811240 |
@sinisaos ahh sweet, thanks for the quick solution! However, is this still a bug? wouldn't we want piccolo to reflect raw aiosqlite in terms of consistency? Also noticed that the Decimal column is not shown in the documentation for the stable branch, not a big deal but just something to point out. |
@vertyco No problem. I don't think it's a bug. Sqlite only has an
There is a hint in the |
I dont think I am quite following the logic behind that. We want to store a large integer but have to use a column type that returns a decimal, yet SQLite's integer column itself is sufficient for storing those when used directly without Piccolo. Sorry if i'm just misunderstanding something, I certainly would like to if that's the case. It just seems like there is such a clear inconsistency between the ORM and what the column type should be capable of storing to me. |
@vertyco I'm sorry, but that's just my opinion. Probably @dantownsend (the author of Piccolo) has a better explanation (or solution) than I do. |
No worries! Just wanted to make sure i'm not missing something that went over my head. |
Maybe the solution could be something like this # in piccolo/columns/column_types.py
class BigInt(Integer):
...
def _get_column_type(self, engine_type: str):
if engine_type == "postgres":
return "BIGINT"
elif engine_type == "cockroach":
return "BIGINT"
elif engine_type == "sqlite":
return "NUMERIC" # <- this is change
raise Exception("Unrecognized engine type")
... Than usage will be from piccolo.columns import Serial, Numeric, Decimal, BigInt
class SomeTable(Table, db=DB):
id: Serial
# Discord Guild ID
num1 = BigInt()
num2 = Numeric()
num3 = Decimal() Result is: PICCOLO
num1 625757527765811240
num2 625757527765811240
num3 625757527765811240
---
aiosqlite
num1 625757527765811240
num2 625757527765811240
num3 625757527765811240 With this small change the Piccolo unit test passed. Cheers |
While that may mask the issue on the surface, the underlying problem is the data type that it returns. class SomeTable(Table, db=DB):
id: Serial
# Discord Guild ID
num1 = BigInt()
num2 = Integer()
num3 = Numeric() Running the same code but printing out the type, we get the following:
The problem is that it Hopefully @dantownsend can give some input on this |
@vertyco Looks like you were right about it being a bug. I think the problem is with this converter. piccolo/piccolo/engine/sqlite.py Lines 174 to 178 in 7373a84
If we run the Python interpreter, we get this. >>> int(float(625757527765811240))
625757527765811200 # wrong
>>> int(625757527765811240)
625757527765811240 # correct If we change return statement to class SomeTable(Table, db=DB):
id: Serial
# Discord Guild ID
num1 = Integer()
num2 = BigInt()
num3 = BigSerial() The result is PICCOLO
num1 625757527765811240 <class 'int'>
num2 625757527765811240 <class 'int'>
num3 625757527765811240 <class 'int'>
---
aiosqlite
num1 625757527765811240
num2 625757527765811240
num3 625757527765811240 |
Ahh nice! Figures its a python limitation with floats. I'll come up with a monkeypatch until this is able to be fixed, thanks for finding it! Here is what i'm using as a workaround for now # __init__.py
import sqlite3
from piccolo.engine import sqlite
@sqlite.decode_to_string
def convert_int_out(value: str) -> int:
return int(value)
sqlite.CONVERTERS["INTEGER"] = convert_int_out
sqlite3.register_converter("INTEGER", convert_int_out) |
@vertyco I tried your workaround and it works :). I can do a PR for this small converter change if @dantownsend is okay with it. |
Thanks both for looking into this. I honestly can't remember why we do @decode_to_string
def convert_int_out(value: str) -> int:
"""
Make sure Integer values are actually of type int.
"""
return int(float(value)) It's as if we're expecting SQLite to return integers as I'll have a look to see if this is ever the case, and if not, will change it to |
I can't see any reason to have |
Issue
Large integers (For example, a Discord guild ID of
625757527765811240
) are not inserted properly when using the SQLiteEngine.The resulting int that actually gets inserted is
625757527765811200
for some reason.When using
aiosqlite
manually I'm able to insert the row normally.How to reproduce
Simply run this code:
It should output the following:
I know BigInt is just an alias for Integer for the sqlite engine but included it just in case, I'm not sure why this happens.
The issue occurs on both Win10 and Ubuntu if that matters, but only tested this script on windows.
Also, been using the postgres engine for a while now. Thanks for making an amazing ORM <3
The text was updated successfully, but these errors were encountered: