Hello.
(first time poster here)
I think I found a bug with sqlmigrate
.
In a model, I went from this unique constraint:
class Meta:
unique_together = ["flight_number", "airline", "scheduled_departure"]
To this:
class Meta:
constraints = [
UniqueConstraint(
TruncDate('scheduled_departure'),
'flight_number',
'airline',
name='unique_flight_per_day'
)
]
And with the second version, the makemigrations
and migrate
commands work, and the index is correctly created, but the sqlimigrate
command breaks:
$ ./manage.py sqlmigrate agoa 0002
[...]
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/core/management/commands/sqlmigrate.py", line 82, in handle
sql_statements = loader.collect_sql(plan)
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/db/migrations/loader.py", line 381, in collect_sql
state = migration.apply(state, schema_editor, collect_sql=True)
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/db/migrations/migration.py", line 132, in apply
operation.database_forwards(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
self.app_label, schema_editor, old_state, project_state
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/db/migrations/operations/models.py", line 673, in database_forwards
alter_together(
~~~~~~~~~~~~~~^
new_model,
^^^^^^^^^^
getattr(old_model._meta, self.option_name, set()),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
getattr(new_model._meta, self.option_name, set()),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/db/backends/base/schema.py", line 607, in alter_unique_together
self._delete_composed_index(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
model,
^^^^^^
...<2 lines>...
self.sql_delete_unique,
^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/mathieu/Library/Application Support/pdm/venvs/agoa-6ezsRtgH-3.13/lib/python3.13/site-packages/django/db/backends/base/schema.py", line 663, in _delete_composed_index
raise ValueError(
...<6 lines>...
)
ValueError: Found wrong number (0) of constraints for agoa_flight(flight_number, airline_id, scheduled_departure)
The funny thing is: the sqlmigrate
command breaks if the migration is applied, but doesn’t if unapplied.
The generated migration:
class Migration(migrations.Migration):
dependencies = [
('agoa', '0001_initial'),
]
operations = [
migrations.AlterUniqueTogether(
name='flight',
unique_together=set(),
),
migrations.AddConstraint(
model_name='flight',
constraint=models.UniqueConstraint(
django.db.models.functions.datetime.TruncDate('scheduled_departure'),
models.F('flight_number'),
models.F('airline'),
name='unique_flight_per_day',
),
),
]
The problem seems to lie into the AlterUniqueTogether
, the sqlmigrate
doesn’t crash anymore if commented.
I went into the sqlite shell to see if the previous constraint was present, and it was, and it looked correct, like what django would expect:
echo "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name='agoa_flight';" | python manage.py dbshell | grep unique
CREATE UNIQUE INDEX "unique_flight_per_day" ON "agoa_flight" ((django_datetime_cast_date("scheduled_departure", 'UTC', 'UTC')), "flight_number", "airline_id")
It looks somewhat like #31834 (Cannot sqlmigrate on Django migrations that change unique_together) – Django, but I think it’s different though:
Mariusz comment says:
In both scenarios a constraint doesn’t exist in the database and cannot be introspected, sqlmigrate works properly if you first apply a migration which adds a constraint.
But here, the constraint exists.
I am asking here to avoid creating useless noise on the ticket trac.