From 71dda1918408a5b15d27c5b2cd28fddcd747449d Mon Sep 17 00:00:00 2001
From: Malcolm Tredinnick <malcolm.tredinnick@gmail.com>
Date: Thu, 28 Aug 2008 05:42:05 +0000
Subject: [PATCH] Fixed #8597 -- Allow the use of strings containing
 underscores and percentage signs in "iexact" queries on PostgreSQL again
 (this case was missed in [8536]).

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8646 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/db/backends/__init__.py              |  4 ++++
 django/db/backends/postgresql/operations.py |  2 ++
 django/db/models/fields/__init__.py         |  2 +-
 tests/regressiontests/queries/models.py     | 12 ++++++++++++
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index 074fa0ed70..be7aac4c03 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -301,6 +301,10 @@ class BaseDatabaseOperations(object):
         from django.utils.encoding import smart_unicode
         return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
 
+    # Same as prep_for_like_query(), but called for "iexact" matches, which
+    # need not necessarily be implemented using "LIKE" in the backend.
+    prep_for_iexact_query = prep_for_like_query
+
     def value_to_db_date(self, value):
         """
         Transform a date value to an object compatible with what is expected
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
index 01cc1fc8b7..235210939f 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -142,3 +142,5 @@ class DatabaseOperations(BaseDatabaseOperations):
     def savepoint_rollback_sql(self, sid):
         return "ROLLBACK TO SAVEPOINT %s" % sid
 
+    def prep_for_iexact_query(self, x):
+        return x
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 5c21e7db73..d3fb27b948 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -205,7 +205,7 @@ class Field(object):
         elif lookup_type in ('contains', 'icontains'):
             return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
         elif lookup_type == 'iexact':
-            return [connection.ops.prep_for_like_query(value)]
+            return [connection.ops.prep_for_iexact_query(value)]
         elif lookup_type in ('startswith', 'istartswith'):
             return ["%s%%" % connection.ops.prep_for_like_query(value)]
         elif lookup_type in ('endswith', 'iendswith'):
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index e2d56e185f..c524c6250e 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -901,6 +901,18 @@ Pickling of DateQuerySets used to fail
 >>> qs = Item.objects.dates('created', 'month')
 >>> _ = pickle.loads(pickle.dumps(qs))
 
+Bug #8597: regression tests for case-insensitive comparisons
+>>> _ = Item.objects.create(name="a_b", created=datetime.datetime.now(), creator=a2, note=n1)
+>>> _ = Item.objects.create(name="x%y", created=datetime.datetime.now(), creator=a2, note=n1)
+>>> Item.objects.filter(name__iexact="A_b")
+[<Item: a_b>]
+>>> Item.objects.filter(name__iexact="x%Y")
+[<Item: x%y>]
+>>> Item.objects.filter(name__istartswith="A_b")
+[<Item: a_b>]
+>>> Item.objects.filter(name__iendswith="A_b")
+[<Item: a_b>]
+
 """}
 
 # In Python 2.3 and the Python 2.6 beta releases, exceptions raised in __len__