Opened 3 months ago

Closed 3 months ago

Last modified 3 months ago

#33052 closed Bug (wontfix)

save() on object with pk with default and existing value results in error and not update.

Reported by: Vikash Singh Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords:
Cc: vikash.duliajan@…, Vikash Singh Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

file with Test case

# This test case works fine.
def test_save_primary_with_default(self):
        # An UPDATE attempt is skipped when a primary key has default.
        with self.assertNumQueries(1):
            PrimaryKeyWithDefault().save()

# This new test case fails.
def test_update_primary_with_default(self):
        obj = PrimaryKeyWithDefault()
        obj.save()
        obj_2 = PrimaryKeyWithDefault(uuid=obj.uuid)
        obj_2.save()

Error stack trace:

Traceback (most recent call last):
  File "/Users/vikash/Documents/django3.2/tests/basic/tests.py", line 165, in test_update_primary_with_default
    obj_2.save()
  File "/Users/vikash/Documents/django3.2/django/db/models/base.py", line 802, in save
    self.save_base(
  File "/Users/vikash/Documents/django3.2/django/db/models/base.py", line 853, in save_base
    updated = self._save_table(
  File "/Users/vikash/Documents/django3.2/django/db/models/base.py", line 1006, in _save_table
    results = self._do_insert(
  File "/Users/vikash/Documents/django3.2/django/db/models/base.py", line 1047, in _do_insert
    return manager._insert(
  File "/Users/vikash/Documents/django3.2/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/vikash/Documents/django3.2/django/db/models/query.py", line 1426, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/Users/vikash/Documents/django3.2/django/db/models/sql/compiler.py", line 1630, in execute_sql
    cursor.execute(sql, params)
  File "/Users/vikash/Documents/django3.2/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(
  File "/Users/vikash/Documents/django3.2/django/db/backends/utils.py", line 79, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/vikash/Documents/django3.2/django/db/backends/utils.py", line 92, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/vikash/Documents/django3.2/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/vikash/Documents/django3.2/django/db/backends/utils.py", line 92, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/vikash/Documents/django3.2/django/db/backends/mysql/base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "/Users/vikash/.virtualenvs/django3.2/lib/python3.9/site-packages/MySQLdb/cursors.py", line 206, in execute
    res = self._query(query)
  File "/Users/vikash/.virtualenvs/django3.2/lib/python3.9/site-packages/MySQLdb/cursors.py", line 319, in _query
    db.query(q)
  File "/Users/vikash/.virtualenvs/django3.2/lib/python3.9/site-packages/MySQLdb/connections.py", line 259, in query
    _mysql.connection.query(self, query)
django.db.utils.IntegrityError: (1062, "Duplicate entry '3023cab946d44309a1bdfa8237705ee7' for key 'basic_primarykeywithdefault.PRIMARY'")

A workaround is present if we fetch the entry from the db first and then update the values and save it.

Another workaround is to set the value of _state.adding as False.

# This new test case passes.
def test_update_primary_with_default(self):
        obj = PrimaryKeyWithDefault()
        obj.save()
        obj_2 = PrimaryKeyWithDefault(uuid=obj.uuid)
        obj_2._state.adding = False
        obj_2.save()

before calling save on it.

This issue is not present in django version = 2.2. The error occurs because additional check was introduced in commit to resolve ticket.

Django test suit has a bunch of tests Example_1, Example_2 (At this point there is already an entry in db in table Site with id=1, and domain='example.com'), where objects are updated based on primary key and not fetched from db and then updated. While those test cases pass if the primary key field is integer or auto increment, if some one changes primary key to uuid they fail.

Change History (3)

comment:1 Changed 3 months ago by Vikash Singh

Cc: Vikash Singh added

comment:2 Changed 3 months ago by Mariusz Felisiak

Resolution: wontfix
Status: newclosed

This is an intended and documented change in the previous behavior.

comment:3 Changed 3 months ago by Mariusz Felisiak

Summary: calling save on object with p_key as UUIDField and value already present in db results in error and not updatesave() on object with pk with default and existing value results in error and not update.
Note: See TracTickets for help on using tickets.
Back to Top