#30526: migration to UUID id field doesn't properly convert integers (SQLite)
------------------------------+--------------------------------------
     Reporter:  Martin Baker  |                    Owner:  nobody
         Type:  Bug           |                   Status:  new
    Component:  Migrations    |                  Version:  2.2
     Severity:  Normal        |               Resolution:
     Keywords:  UUID          |             Triage Stage:  Unreviewed
    Has patch:  0             |      Needs documentation:  0
  Needs tests:  0             |  Patch needs improvement:  0
Easy pickings:  0             |                    UI/UX:  0
------------------------------+--------------------------------------
Description changed by Martin Baker:

Old description:

> This may be present in other DBs, but I've noticed it with SQLite under
> Django 2.2.1.
>
> Steps to reproduce:
>
> 1. Start a model with an implicit integer id, and create and run the
> migration:
>
> {{{#!python
> from django.db import models
>
> class Something(models.Model):
>     name = models.CharField(max_length=32)
> }}}
>
> 2. Then create one instance via the shell (`python manage.py shell`):
>
> {{{#!python
> from uuidbug.models import Something
> s = Something(name="One")
> s.save()
> }}}
>
> In the DB it looks like this (can use `python manage.py dbshell`):
> {{{
> sqlite> .headers on
> sqlite> select * from uuiditem_something;
> name|id
> One|1
> }}}
>
> 3. Edit the model to use UUIDs:
>
> {{{#!python
> import uuid
>
> from django.db import models
>
> class Something(models.Model):
>     name = models.CharField(max_length=32)
>     id = models.UUIDField(primary_key=True, default=uuid.uuid4,
> editable=False)
> }}}
>
> 4. After creating and running the migration, add another instance:
>
> {{{#!python
> from uuidbug.models import Something
> s = Something(name="After UUID-ization")
> s.save()
> }}}
>
> DB now looks like this:
>
> {{{
> sqlite> select * from uuiditem_something;
> name|id
> One|1
> After UUID-ization|693e1942d7d142289bb9fb3664f2c11a
> }}}
>
> Note that the id for the first instance has not been converted to a UUID
> properly. If you try to access the objects, you get an error:
>
> {{{#!python
> >>> Something.objects.all()
> Traceback (most recent call last):
>   File "<console>", line 1, in <module>
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/manager.py", line 82, in manager_method
>     return getattr(self.get_queryset(), name)(*args, **kwargs)
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/query.py", line 653, in first
>     for obj in (self if self.ordered else self.order_by('pk'))[:1]:
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/query.py", line 274, in __iter__
>     self._fetch_all()
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/query.py", line 1242, in _fetch_all
>     self._result_cache = list(self._iterable_class(self))
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/query.py", line 72, in __iter__
>     for row in compiler.results_iter(results):
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/models/sql/compiler.py", line 1044, in
> apply_converters
>     value = converter(value, expression, connection)
>   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
> packages/django/db/backends/sqlite3/operations.py", line 294, in
> convert_uuidfield_value
>     value = uuid.UUID(value)
>   File
> "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/uuid.py",
> line 160, in __init__
>     raise ValueError('badly formed hexadecimal UUID string')
> ValueError: badly formed hexadecimal UUID string
> }}}

New description:

 This may be present in other DBs, but I've noticed it with SQLite under
 Django 2.2.1.

 Steps to reproduce:

 1. Start a model with an implicit integer id, and create and run the
 migration:

 {{{#!python
 from django.db import models

 class Something(models.Model):
     name = models.CharField(max_length=32)
 }}}

 2. Then create one instance via the shell (`python manage.py shell`):

 {{{#!python
 from uuidbug.models import Something
 s = Something(name="One")
 s.save()
 }}}

 In the DB it looks like this (can use `python manage.py dbshell`):
 {{{
 sqlite> .headers on
 sqlite> select * from uuiditem_something;
 name|id
 One|1
 }}}

 3. Edit the model to use UUIDs:

 {{{#!python
 import uuid

 from django.db import models

 class Something(models.Model):
     name = models.CharField(max_length=32)
     id = models.UUIDField(primary_key=True, default=uuid.uuid4,
 editable=False)
 }}}

 4. After creating and running the migration, add another instance:

 {{{#!python
 from uuidbug.models import Something
 s = Something(name="After UUID-ization")
 s.save()
 }}}

 DB now looks like this:

 {{{
 sqlite> select * from uuidbug_something;
 name|id
 One|1
 After UUID-ization|693e1942d7d142289bb9fb3664f2c11a
 }}}

 Note that the id for the first instance has not been converted to a UUID
 properly. If you try to access the objects, you get an error:

 {{{#!python
 >>> Something.objects.all()
 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/manager.py", line 82, in manager_method
     return getattr(self.get_queryset(), name)(*args, **kwargs)
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/query.py", line 653, in first
     for obj in (self if self.ordered else self.order_by('pk'))[:1]:
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/query.py", line 274, in __iter__
     self._fetch_all()
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/query.py", line 1242, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/query.py", line 72, in __iter__
     for row in compiler.results_iter(results):
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 1044, in apply_converters
     value = converter(value, expression, connection)
   File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-
 packages/django/db/backends/sqlite3/operations.py", line 294, in
 convert_uuidfield_value
     value = uuid.UUID(value)
   File
 
"/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/uuid.py",
 line 160, in __init__
     raise ValueError('badly formed hexadecimal UUID string')
 ValueError: badly formed hexadecimal UUID string
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30526#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/065.c70718f280eb6e2b41fa4b1ada65c781%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to