1
0
mirror of https://github.com/django/django.git synced 2025-04-19 06:44:36 +00:00

[1.7.x] Fixed #24605 -- Fixed incorrect reference to alias in subquery.

Thanks to charettes and priidukull for investigating the issue, and to
kurevin for the report.

Backport of 355c5edd9390caad5725375abca03460805f663b from master
This commit is contained in:
Anssi Kääriäinen 2015-04-16 08:39:31 +03:00 committed by Tim Graham
parent bcb536004a
commit c3a9820251
4 changed files with 67 additions and 21 deletions

View File

@ -56,7 +56,8 @@ class SQLCompiler(object):
if name in self.quote_cache:
return self.quote_cache[name]
if ((name in self.query.alias_map and name not in self.query.table_map) or
name in self.query.extra_select or name in self.query.external_aliases):
name in self.query.extra_select or (
name in self.query.external_aliases and name not in self.query.table_map)):
self.quote_cache[name] = name
return name
r = self.connection.ops.quote_name(name)

View File

@ -4,5 +4,9 @@ Django 1.7.8 release notes
*Under development*
Django 1.7.8 fixes database introspection with SQLite 3.8.9 (released April 8,
2015) (:ticket:`24637`).
Django 1.7.8 fixes:
* Database introspection with SQLite 3.8.9 (released April 8, 2015)
(:ticket:`24637`).
* A database table name quoting regression in 1.7.2 (:ticket:`24605`).

View File

@ -690,3 +690,18 @@ class Ticket23605B(models.Model):
class Ticket23605C(models.Model):
field_c0 = models.FloatField()
# db_table names have capital letters to ensure they are quoted in queries.
class Individual(models.Model):
alive = models.BooleanField(default=False)
class Meta:
db_table = 'Individual'
class RelatedIndividual(models.Model):
related = models.ForeignKey(Individual, related_name='related_individual')
class Meta:
db_table = 'RelatedIndividual'

View File

@ -1,35 +1,37 @@
from __future__ import unicode_literals
from collections import OrderedDict
import datetime
from operator import attrgetter
import pickle
import unittest
import warnings
from collections import OrderedDict
from operator import attrgetter
from django.core.exceptions import FieldError
from django.db import connection, DEFAULT_DB_ALIAS
from django.db.models import Count, F, Q
from django.db.models.sql.where import WhereNode, EverythingNode, NothingNode
from django.db import DEFAULT_DB_ALIAS, connection
from django.db.models import F, Q, Count
from django.db.models.sql.datastructures import EmptyResultSet
from django.db.models.sql.where import EverythingNode, NothingNode, WhereNode
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import str_prefix, CaptureQueriesContext
from django.test.utils import CaptureQueriesContext, str_prefix
from django.utils import six
from django.utils.six.moves import range
from .models import (
Annotation, Article, Author, Celebrity, Child, Cover, Detail, DumbCategory,
ExtraInfo, Fan, Item, LeafA, Join, LeafB, LoopX, LoopZ, ManagedModel,
Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related,
Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA,
ObjectB, ObjectC, CategoryItem, SimpleCategory, SpecialCategory,
OneToOneCategory, NullableName, ProxyCategory, SingleObject, RelatedObject,
ModelA, ModelB, ModelC, ModelD, Responsibility, Job, JobResponsibilities,
BaseA, FK1, Identifier, Program, Channel, Page, Paragraph, Chapter, Book,
MyObject, Order, OrderItem, SharedConnection, Task, Staff, StaffUser,
CategoryRelationship, Ticket21203Parent, Ticket21203Child, Person,
Company, Employment, CustomPk, CustomPkTag, Classroom, School, Student,
Ticket23605A, Ticket23605B, Ticket23605C)
FK1, X, Annotation, Article, Author, BaseA, Book, CategoryItem,
CategoryRelationship, Celebrity, Channel, Chapter, Child, Classroom,
Company, Cover, CustomPk, CustomPkTag, Detail, DumbCategory, Eaten,
Employment, ExtraInfo, Fan, Food, Identifier, Individual, Item, Job,
JobResponsibilities, Join, LeafA, LeafB, LoopX, LoopZ, ManagedModel,
Member, ModelA, ModelB, ModelC, ModelD, MyObject, NamedCategory, Node,
Note, NullableName, Number, ObjectA, ObjectB, ObjectC, OneToOneCategory,
Order, OrderItem, Page, Paragraph, Person, Plaything, PointerA, Program,
ProxyCategory, Ranking, Related, RelatedIndividual, RelatedObject, Report,
ReservedName, Responsibility, School, SharedConnection, SimpleCategory,
SingleObject, SpecialCategory, Staff, StaffUser, Student, Tag, Task,
Ticket21203Child, Ticket21203Parent, Ticket23605A, Ticket23605B,
Ticket23605C, TvChef, Valid,
)
class BaseQuerysetTest(TestCase):
@ -3448,3 +3450,27 @@ class Ticket23605Tests(TestCase):
self.assertQuerysetEqual(qs1, [a1], lambda x: x)
qs2 = Ticket23605A.objects.exclude(complex_q)
self.assertQuerysetEqual(qs2, [a2], lambda x: x)
class TestTicket24605(TestCase):
def test_ticket_24605(self):
"""
Subquery table names should be quoted.
"""
i1 = Individual.objects.create(alive=True)
RelatedIndividual.objects.create(related=i1)
i2 = Individual.objects.create(alive=False)
RelatedIndividual.objects.create(related=i2)
i3 = Individual.objects.create(alive=True)
i4 = Individual.objects.create(alive=False)
self.assertQuerysetEqual(
Individual.objects.filter(Q(alive=False), Q(related_individual__isnull=True)),
[i4], lambda x: x
)
self.assertQuerysetEqual(
Individual.objects.exclude(
Q(alive=False), Q(related_individual__isnull=True)
).order_by('pk'),
[i1, i2, i3], lambda x: x
)