django-oscar / django-oscar-api

RESTful JSON API for django-oscar

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OverflowError: Python int too large to convert to SQLite INTEGER

jayvdb opened this issue · comments

Similar to #226, using schemathesis, I run into a lot of

OverflowError: Python int too large to convert to SQLite INTEGER

There is one issue in DRF about this

encode/django-rest-framework#7134

And I intent to raise another one, and submit a PR for one, but it occurs all over the place and need a few local patches until Django core takes up the issue themselves.

Here are a few of them

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 239, in get
    return self.list(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/mixins.py", line 38, in list
    queryset = self.filter_queryset(self.get_queryset())
  File "/usr/lib/python3.8/site-packages/oscarapi/views/basket.py", line 293, in get_queryset
    basket = self.check_basket_permission(self.request, basket_pk=basket_pk)
  File "/usr/lib/python3.8/site-packages/oscarapi/views/utils.py", line 54, in check_basket_permission
    basket = generics.get_object_or_404(Basket.objects, pk=basket_pk)
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 19, in get_object_or_404
    return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
  File "/usr/lib/python3.8/site-packages/django/shortcuts.py", line 76, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 411, in get
    num = len(clone)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 258, in __len__
    self._fetch_all()
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 1261, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 57, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/usr/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1152, in execute_sql
    cursor.execute(sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/usr/lib64/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 115, in debug_sql
    sql = self.db.ops.last_executed_query(self.cursor, sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 152, in last_executed_query
    params = self._quote_params_for_last_executed_query(params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 141, in _quote_params_for_last_executed_query
    return cursor.execute(sql, params).fetchone()
OverflowError: Python int too large to convert to SQLite INTEGER
[03:12:36][ERROR] django.request log.py:log_response:222 | Internal Server Error: /oscarapi/baskets/9223372036854775808/lines/
[03:12:36][ERROR] django.server basehttp.py:log_message:157 | "GET /oscarapi/baskets/9223372036854775808/lines/ HTTP/1.1" 500 164
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 285, in put
    return self.update(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/mixins.py", line 65, in update
    instance = self.get_object()
  File "/usr/lib/python3.8/site-packages/oscarapi/views/basic.py", line 91, in get_object
    basket = super(BasketDetail, self).get_object()
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 96, in get_object
    obj = get_object_or_404(queryset, **filter_kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 19, in get_object_or_404
    return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
  File "/usr/lib/python3.8/site-packages/django/shortcuts.py", line 76, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 411, in get
    num = len(clone)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 258, in __len__
    self._fetch_all()
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 1261, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 57, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/usr/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1152, in execute_sql
    cursor.execute(sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/usr/lib64/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 115, in debug_sql
    sql = self.db.ops.last_executed_query(self.cursor, sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 152, in last_executed_query
    params = self._quote_params_for_last_executed_query(params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 141, in _quote_params_for_last_executed_query
    return cursor.execute(sql, params).fetchone()
OverflowError: Python int too large to convert to SQLite INTEGER
[03:28:26][ERROR] django.request log.py:log_response:222 | Internal Server Error: /oscarapi/baskets/9223372071222935553/
[03:28:26][ERROR] django.server basehttp.py:log_message:157 | "PUT /oscarapi/baskets/9223372071222935553/ HTTP/1.1" 500 164
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 285, in put
    return self.update(request, *args, **kwargs)
  File "/usr/lib/python3.8/site-packages/rest_framework/mixins.py", line 65, in update
    instance = self.get_object()
  File "/usr/lib/python3.8/site-packages/rest_framework/generics.py", line 83, in get_object
    queryset = self.filter_queryset(self.get_queryset())
  File "/usr/lib/python3.8/site-packages/oscarapi/views/basket.py", line 325, in get_queryset
    basket = get_object_or_404(operations.editable_baskets(), pk=basket_pk)
  File "/usr/lib/python3.8/site-packages/django/shortcuts.py", line 76, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 411, in get
    num = len(clone)
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 258, in __len__
    self._fetch_all()
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 1261, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/lib/python3.8/site-packages/django/db/models/query.py", line 57, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/usr/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1152, in execute_sql
    cursor.execute(sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/usr/lib64/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3.8/site-packages/django/db/backends/utils.py", line 115, in debug_sql
    sql = self.db.ops.last_executed_query(self.cursor, sql, params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 152, in last_executed_query
    params = self._quote_params_for_last_executed_query(params)
  File "/usr/lib/python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 141, in _quote_params_for_last_executed_query
    return cursor.execute(sql, params).fetchone()
OverflowError: Python int too large to convert to SQLite INTEGER
[05:40:41][ERROR] django.request log.py:log_response:222 | Internal Server Error: /oscarapi/baskets/9223372036854775808/lines/0/
[05:40:41][ERROR] django.server basehttp.py:log_message:157 | "PUT /oscarapi/baskets/9223372036854775808/lines/0/ HTTP/1.1" 500 164

Thanks for the effort and the report but this has unfortunately nothing to do with OscarAPI.

I also think that this is not something DRF should handle, as it's something specific to sqlite3 and it's integer value limitations. It's a low level exception that says to you that your having a serious problem. So the "Internal Server Error" is actually something you want to see (and not be replaced in any other message) as this is really a bad thing and should be fixed in the correct layer.

I guess that if this needs some specific attention, the sqlite3 backend of django is the place for it.

Thanks for merging #228 - your reasoning there is why I put up that patch - it at least channels these errors through one pathway.

Your reasoning here is exactly why I didnt put up the hackier fixes. I agree the problem isn't OscarAPI, as I see it in other apps also.

However IMO it "should" be fixed in DRF core, as the very large ID that it is processing can not possibly be in the underlying data on the connected database, due to the same underlying limitation causing the OverflowError, so 404 is a reasonable quick answer, and would have been the answer if connected to a different backend. Where to detect the overflow may still need fine tuning, and fingers crossed it can be fine tuned enough to eliminate any cases where 404 might not be an appropriate answer.

(I also suspect that the sqlite driver may be part of the problem, so I am not saying you are wrong there - I dont know enough about it to say for sure.)

A 404 in a GET query would something I'd say is worth discussing in the implementation of the DRF specific part where it occurs. You already opened up encode/django-rest-framework#7448 which is the right place for it I guess.