Fixed #32858 -- Fixed ExclusionConstraint crash with index transforms in expressions.

This commit is contained in:
Lucidiot 2021-06-17 21:54:08 +02:00 committed by Mariusz Felisiak
parent 501a371411
commit b69b0c3fe8
3 changed files with 20 additions and 1 deletions

View File

@ -561,6 +561,7 @@ answer newbie questions, and generally made Django that much better:
Luan Pablo <luanpab@gmail.com>
Lucas Connors <https://www.revolutiontech.ca/>
Luciano Ramalho
Lucidiot <lucidiot@brainshit.fr>
Ludvig Ericson <ludvig.ericson@gmail.com>
Luis C. Berrocal <luis.berrocal.1942@gmail.com>
Łukasz Langa <lukasz@langa.pl>

View File

@ -2,6 +2,7 @@ from django.db import NotSupportedError
from django.db.backends.ddl_references import Statement, Table
from django.db.models import Deferrable, F, Q
from django.db.models.constraints import BaseConstraint
from django.db.models.expressions import Col
from django.db.models.sql import Query
__all__ = ['ExclusionConstraint']
@ -73,6 +74,8 @@ class ExclusionConstraint(BaseConstraint):
expression = F(expression)
expression = expression.resolve_expression(query=query)
sql, params = compiler.compile(expression)
if not isinstance(expression, Col):
sql = f'({sql})'
try:
opclass = self.opclasses[idx]
if opclass:

View File

@ -14,7 +14,9 @@ from django.test import modify_settings, skipUnlessDBFeature
from django.utils import timezone
from . import PostgreSQLTestCase
from .models import HotelReservation, RangesModel, Room, Scene
from .models import (
HotelReservation, IntegerArrayModel, RangesModel, Room, Scene,
)
try:
from psycopg2.extras import DateRange, NumericRange
@ -670,6 +672,19 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
self.get_constraints(HotelReservation._meta.db_table),
)
def test_index_transform(self):
constraint_name = 'first_index_equal'
constraint = ExclusionConstraint(
name=constraint_name,
expressions=[('field__0', RangeOperators.EQUAL)],
)
with connection.schema_editor() as editor:
editor.add_constraint(IntegerArrayModel, constraint)
self.assertIn(
constraint_name,
self.get_constraints(IntegerArrayModel._meta.db_table),
)
def test_range_adjacent_initially_deferred(self):
constraint_name = 'ints_adjacent_deferred'
self.assertNotIn(constraint_name, self.get_constraints(RangesModel._meta.db_table))