mirror of
https://github.com/django/django.git
synced 2025-11-18 11:00:24 +00:00
Fix incorrect SQL generation for CheckConstraint with OR
Ensure CheckConstraint does not use qualified column names in SQL when combining OR and AND, preventing migration failures on SQLite and Oracle. Fixes malformed schema errors by generating constraint SQL with unqualified column names.
This commit is contained in:
parent
6866c91b63
commit
794017b83a
2 changed files with 79 additions and 1 deletions
|
|
@ -1338,7 +1338,7 @@ class Query(BaseExpression):
|
|||
if isinstance(child, Node):
|
||||
child_clause, needed_inner = self._add_q(
|
||||
child, used_aliases, branch_negated,
|
||||
current_negated, allow_joins, split_subq)
|
||||
current_negated, allow_joins, split_subq, simple_col)
|
||||
joinpromoter.add_votes(needed_inner)
|
||||
else:
|
||||
child_clause, needed_inner = self.build_filter(
|
||||
|
|
|
|||
|
|
@ -79,6 +79,84 @@ class CheckConstraintTests(TestCase):
|
|||
expected_name = 'price_gt_discounted_price'
|
||||
self.assertIn(expected_name, constraints)
|
||||
|
||||
def test_check_constraint_sql_with_or(self):
|
||||
"""
|
||||
Test that CheckConstraint with OR operator generates correct SQL
|
||||
without table qualifiers on SQLite and Oracle.
|
||||
"""
|
||||
from django.db import connection
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.models.sql.query import Query
|
||||
|
||||
# Create a temporary model for testing
|
||||
class TempModel1(models.Model):
|
||||
field_1 = models.IntegerField(blank=True, null=True)
|
||||
flag = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
app_label = 'constraints'
|
||||
db_table = 'temp_test_constraint'
|
||||
|
||||
# Create the constraint with OR operator
|
||||
constraint_check = models.Q(flag__exact=True, field_1__isnull=False) | models.Q(flag__exact=False)
|
||||
|
||||
# Generate the check SQL directly
|
||||
query = Query(model=TempModel1)
|
||||
where = query.build_where(constraint_check)
|
||||
compiler = query.get_compiler(connection=connection)
|
||||
sql, params = where.as_sql(compiler, connection)
|
||||
|
||||
# The SQL should not contain any table qualifiers
|
||||
# It should look like: (("field_1" IS NOT NULL AND "flag" = 1) OR "flag" = 0)
|
||||
# NOT like: (("temp_test_constraint"."field_1" IS NOT NULL...
|
||||
self.assertNotIn('temp_test_constraint.', sql.lower())
|
||||
self.assertNotIn('new__temp_test_constraint.', sql.lower())
|
||||
|
||||
# Verify that both parts of the OR clause use simple column names
|
||||
# The flag field appears in both parts, so check it's not qualified
|
||||
self.assertIn('"flag"', sql)
|
||||
# Make sure field_1 is present and not qualified
|
||||
self.assertIn('"field_1"', sql)
|
||||
|
||||
def test_check_constraint_sql_with_nested_or_and(self):
|
||||
"""
|
||||
Test that CheckConstraint with nested OR and AND operators generates
|
||||
correct SQL without table qualifiers.
|
||||
"""
|
||||
from django.db import connection
|
||||
from django.db.models.sql.query import Query
|
||||
|
||||
# Create a temporary model for testing
|
||||
class TempModel2(models.Model):
|
||||
field_1 = models.IntegerField(blank=True, null=True)
|
||||
field_2 = models.IntegerField(blank=True, null=True)
|
||||
flag = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
app_label = 'constraints'
|
||||
db_table = 'temp_test_constraint_nested'
|
||||
|
||||
# Create a more complex constraint with nested OR and AND
|
||||
constraint_check = (
|
||||
models.Q(flag__exact=True, field_1__isnull=False, field_2__gt=0) |
|
||||
models.Q(flag__exact=False) |
|
||||
models.Q(field_1__exact=0, field_2__exact=0)
|
||||
)
|
||||
|
||||
# Generate the check SQL directly
|
||||
query = Query(model=TempModel2)
|
||||
where = query.build_where(constraint_check)
|
||||
compiler = query.get_compiler(connection=connection)
|
||||
sql, params = where.as_sql(compiler, connection)
|
||||
|
||||
# The SQL should not contain any table qualifiers
|
||||
self.assertNotIn('temp_test_constraint_nested.', sql.lower())
|
||||
|
||||
# Verify all fields are present without table qualifiers
|
||||
self.assertIn('"flag"', sql)
|
||||
self.assertIn('"field_1"', sql)
|
||||
self.assertIn('"field_2"', sql)
|
||||
|
||||
|
||||
class UniqueConstraintTests(TestCase):
|
||||
@classmethod
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue