Opened 6 years ago

Last modified 18 months ago

#27813 new Bug

BinaryField type inconsistent between sqlite3 (bytes) and postgresql (memoryview)

Reported by: Antonio Terceiro Owned by: nobody
Component: Database layer (models, ORM) Version: 3.1
Severity: Normal Keywords:
Cc: Egor R Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


I have an application that has the following model:

class Attachment(models.Model):
    # ...
    data = models.BinaryField(default=None)

under sqlite3:

In [1]: Attachment.objects.last().data
Out[1]: b'Mon Feb  6 16:53:37 UTC 2017\n'

under postgresql:

In [1]: Attachment.objects.last().data
Out[1]: <memory at 0x7f1ae8e93108>

i.e. under sqlite the BinaryField values comes as bytes(), and under postgresql it comes as memoryview()

Change History (9)

comment:1 Changed 6 years ago by Tim Graham

I can confirm the difference, however, I can't say if a change should be made. Do you have a suggestion about what to do?

comment:2 Changed 6 years ago by Antonio Terceiro

I noticed this because I had a test that checked the value of the data field after a given operation, and since I was initially developing against sqlite, I compared the value against a bytes() literal b'...'. to make the test pass against postgresql as well, I had to cast the value in the database to bytes() before the comparison.

I would expect to always get the same type, either bytes or memoryview. on the other hand, everything else other than that one test just worked. the view that allows for that data to be downloaded worked just fine, because bytes and memoryview have a similar enough interface, so maybe this should be just clearly documented.

comment:3 Changed 6 years ago by Tim Graham

Summary: BinaryField is inconsistent between sqlite3 and postgresqlBinaryField type inconsistent between sqlite3 (bytes) and postgresql (memoryview)
Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

Django's test suite is also casting to bytes for comparison. Accepting for further investigation.

comment:4 Changed 5 years ago by Václav Řehák

The same applies to Oracle backend which also returns bytes. One of the reasons we use Django in current project is that we can run it on Oracle (as needed due to historical reasons) but hopefully convert it to PostgreSQL one day. Subtle differences like this make it more complicated. What is the reason to return different data type from PostgreSQL backend?

comment:5 Changed 5 years ago by Tim Graham

My guess is that's how the database or database driver (psycopg2) works.

comment:6 Changed 4 years ago by Stavros Korokithakis

I am hit by this as well. Returning HttpResponse(mymodel.mybinaryfield) returns a literal <memory object at 0xdeadbeef> string instead of the data on Postgres.

comment:7 Changed 2 years ago by Benjamin Matschke

When using BinaryField as a primary key, it leads to a bug.
For example deleting such a table raises a

TypeError: '<' not supported between instances of 'memoryview' and 'memoryview'

Besides, the resulting type should be consistent, independent on the underlying database.

comment:8 Changed 2 years ago by Benjamin Matschke

Type: Cleanup/optimizationBug
Version: 1.103.1

comment:9 Changed 18 months ago by Egor R

Cc: Egor R added
Note: See TracTickets for help on using tickets.
Back to Top