Refs #32096 -- Fixed ExclusionConstraint crash with JSONField key transforms in expressions.
Regression in 6789ded0a6
.
This commit is contained in:
parent
bbd55e5863
commit
ee0abac169
|
@ -72,7 +72,7 @@ class ExclusionConstraint(BaseConstraint):
|
||||||
if isinstance(expression, str):
|
if isinstance(expression, str):
|
||||||
expression = F(expression)
|
expression = F(expression)
|
||||||
expression = expression.resolve_expression(query=query)
|
expression = expression.resolve_expression(query=query)
|
||||||
sql, params = expression.as_sql(compiler, schema_editor.connection)
|
sql, params = compiler.compile(expression)
|
||||||
try:
|
try:
|
||||||
opclass = self.opclasses[idx]
|
opclass = self.opclasses[idx]
|
||||||
if opclass:
|
if opclass:
|
||||||
|
|
|
@ -34,3 +34,9 @@ Bugfixes
|
||||||
* Fixed a regression in Django 3.1 that caused a crash of
|
* Fixed a regression in Django 3.1 that caused a crash of
|
||||||
:class:`~django.db.models.ExpressionWrapper` with key transforms for
|
:class:`~django.db.models.ExpressionWrapper` with key transforms for
|
||||||
:class:`~django.db.models.JSONField` (:ticket:`32096`).
|
:class:`~django.db.models.JSONField` (:ticket:`32096`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 3.1 that caused a migrations crash on PostgreSQL
|
||||||
|
when adding an
|
||||||
|
:class:`~django.contrib.postgres.constraints.ExclusionConstraint` with key
|
||||||
|
transforms for :class:`~django.db.models.JSONField` in ``expressions``
|
||||||
|
(:ticket:`32096`).
|
||||||
|
|
|
@ -303,6 +303,7 @@ class Migration(migrations.Migration):
|
||||||
('start', models.DateTimeField()),
|
('start', models.DateTimeField()),
|
||||||
('end', models.DateTimeField()),
|
('end', models.DateTimeField()),
|
||||||
('cancelled', models.BooleanField(default=False)),
|
('cancelled', models.BooleanField(default=False)),
|
||||||
|
('requirements', models.JSONField(blank=True, null=True)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'required_db_vendor': 'postgresql',
|
'required_db_vendor': 'postgresql',
|
||||||
|
|
|
@ -191,3 +191,4 @@ class HotelReservation(PostgreSQLModel):
|
||||||
start = models.DateTimeField()
|
start = models.DateTimeField()
|
||||||
end = models.DateTimeField()
|
end = models.DateTimeField()
|
||||||
cancelled = models.BooleanField(default=False)
|
cancelled = models.BooleanField(default=False)
|
||||||
|
requirements = models.JSONField(blank=True, null=True)
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.db import (
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
CheckConstraint, Deferrable, F, Func, Q, UniqueConstraint,
|
CheckConstraint, Deferrable, F, Func, Q, UniqueConstraint,
|
||||||
)
|
)
|
||||||
|
from django.db.models.fields.json import KeyTextTransform
|
||||||
from django.db.models.functions import Left
|
from django.db.models.functions import Left
|
||||||
from django.test import skipUnlessDBFeature
|
from django.test import skipUnlessDBFeature
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -620,6 +621,22 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
editor.add_constraint(Scene, constraint)
|
editor.add_constraint(Scene, constraint)
|
||||||
self.assertIn(constraint_name, self.get_constraints(Scene._meta.db_table))
|
self.assertIn(constraint_name, self.get_constraints(Scene._meta.db_table))
|
||||||
|
|
||||||
|
def test_expressions_with_key_transform(self):
|
||||||
|
constraint_name = 'exclude_overlapping_reservations_smoking'
|
||||||
|
constraint = ExclusionConstraint(
|
||||||
|
name=constraint_name,
|
||||||
|
expressions=[
|
||||||
|
(F('datespan'), RangeOperators.OVERLAPS),
|
||||||
|
(KeyTextTransform('smoking', 'requirements'), RangeOperators.EQUAL),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.add_constraint(HotelReservation, constraint)
|
||||||
|
self.assertIn(
|
||||||
|
constraint_name,
|
||||||
|
self.get_constraints(HotelReservation._meta.db_table),
|
||||||
|
)
|
||||||
|
|
||||||
def test_range_adjacent_initially_deferred(self):
|
def test_range_adjacent_initially_deferred(self):
|
||||||
constraint_name = 'ints_adjacent_deferred'
|
constraint_name = 'ints_adjacent_deferred'
|
||||||
self.assertNotIn(constraint_name, self.get_constraints(RangesModel._meta.db_table))
|
self.assertNotIn(constraint_name, self.get_constraints(RangesModel._meta.db_table))
|
||||||
|
|
Loading…
Reference in New Issue