#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 [email protected].
To post to this group, send email to [email protected].
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