From feb683c4c2c5ecfb61e4cb490c3e357450c0c0e8 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 14 Mar 2018 10:00:07 +0100 Subject: [PATCH] Fixed #29155 -- Fixed crash when database functions are used with pattern lookups. Thanks Tim Graham and Sergey Fedoseev for reviews. --- django/db/models/lookups.py | 2 +- tests/lookup/models.py | 1 + tests/lookup/tests.py | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py index 00eeda1f39..a4c7459bfe 100644 --- a/django/db/models/lookups.py +++ b/django/db/models/lookups.py @@ -397,7 +397,7 @@ class PatternLookup(BuiltinLookup): def process_rhs(self, qn, connection): rhs, params = super().process_rhs(qn, connection) - if params and not self.bilateral_transforms: + if self.rhs_is_direct_value() and params and not self.bilateral_transforms: params[0] = self.param_pattern % connection.ops.prep_for_like_query(params[0]) return rhs, params diff --git a/tests/lookup/models.py b/tests/lookup/models.py index ef5e7dfb0e..3f1f14dfbc 100644 --- a/tests/lookup/models.py +++ b/tests/lookup/models.py @@ -17,6 +17,7 @@ class Alarm(models.Model): class Author(models.Model): name = models.CharField(max_length=100) + alias = models.CharField(max_length=50, null=True, blank=True) class Meta: ordering = ('name',) diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index 7d7216777c..785d3ea478 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -5,6 +5,7 @@ from operator import attrgetter from django.core.exceptions import FieldError from django.db import connection +from django.db.models.functions import Substr from django.test import TestCase, skipUnlessDBFeature from .models import Article, Author, Game, Player, Season, Tag @@ -878,3 +879,19 @@ class LookupTests(TestCase): season = Season.objects.create(year=2012, nulled_text_field=None) self.assertTrue(Season.objects.filter(pk=season.pk, nulled_text_field__isnull=True)) self.assertTrue(Season.objects.filter(pk=season.pk, nulled_text_field='')) + + def test_pattern_lookups_with_substr(self): + a = Author.objects.create(name='John Smith', alias='Johx') + b = Author.objects.create(name='Rhonda Simpson', alias='sonx') + tests = ( + ('startswith', [a]), + ('istartswith', [a]), + ('contains', [a, b]), + ('icontains', [a, b]), + ('endswith', [b]), + ('iendswith', [b]), + ) + for lookup, result in tests: + with self.subTest(lookup=lookup): + authors = Author.objects.filter(**{'name__%s' % lookup: Substr('alias', 1, 3)}) + self.assertCountEqual(authors, result)