mirror of
https://github.com/django/django.git
synced 2024-12-23 01:25:58 +00:00
Refs #26285 -- Removed MySQL __search lookup per deprecation timeline.
This commit is contained in:
parent
bfe0d54514
commit
5139832398
@ -191,15 +191,6 @@ class BaseDatabaseOperations(object):
|
|||||||
else:
|
else:
|
||||||
return 'FOR UPDATE'
|
return 'FOR UPDATE'
|
||||||
|
|
||||||
def fulltext_search_sql(self, field_name):
|
|
||||||
"""
|
|
||||||
Returns the SQL WHERE clause to use in order to perform a full-text
|
|
||||||
search of the given field_name. Note that the resulting string should
|
|
||||||
contain a '%s' placeholder for the value being searched against.
|
|
||||||
"""
|
|
||||||
# RemovedInDjango20Warning
|
|
||||||
raise NotImplementedError('Full-text search is not implemented for this database backend')
|
|
||||||
|
|
||||||
def last_executed_query(self, cursor, sql, params):
|
def last_executed_query(self, cursor, sql, params):
|
||||||
"""
|
"""
|
||||||
Returns a string of the query last executed by the given cursor, with
|
Returns a string of the query last executed by the given cursor, with
|
||||||
|
@ -110,10 +110,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
"""
|
"""
|
||||||
return [(None, ("NULL", [], False))]
|
return [(None, ("NULL", [], False))]
|
||||||
|
|
||||||
def fulltext_search_sql(self, field_name):
|
|
||||||
# RemovedInDjango20Warning
|
|
||||||
return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
|
|
||||||
|
|
||||||
def last_executed_query(self, cursor, sql, params):
|
def last_executed_query(self, cursor, sql, params):
|
||||||
# With MySQLdb, cursor objects have an (undocumented) "_last_executed"
|
# With MySQLdb, cursor objects have an (undocumented) "_last_executed"
|
||||||
# attribute where the exact query sent to the database is saved.
|
# attribute where the exact query sent to the database is saved.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import itertools
|
import itertools
|
||||||
import math
|
import math
|
||||||
import warnings
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
@ -10,7 +9,6 @@ from django.db.models.fields import (
|
|||||||
DateTimeField, DecimalField, Field, IntegerField,
|
DateTimeField, DecimalField, Field, IntegerField,
|
||||||
)
|
)
|
||||||
from django.db.models.query_utils import RegisterLookupMixin
|
from django.db.models.query_utils import RegisterLookupMixin
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.six.moves import range
|
from django.utils.six.moves import range
|
||||||
|
|
||||||
@ -509,22 +507,6 @@ class IsNull(BuiltinLookup):
|
|||||||
return "%s IS NOT NULL" % sql, params
|
return "%s IS NOT NULL" % sql, params
|
||||||
|
|
||||||
|
|
||||||
@Field.register_lookup
|
|
||||||
class Search(BuiltinLookup):
|
|
||||||
lookup_name = 'search'
|
|
||||||
prepare_rhs = False
|
|
||||||
|
|
||||||
def as_sql(self, compiler, connection):
|
|
||||||
warnings.warn(
|
|
||||||
'The `__search` lookup is deprecated. See the 1.10 release notes '
|
|
||||||
'for how to replace it.', RemovedInDjango20Warning, stacklevel=2
|
|
||||||
)
|
|
||||||
lhs, lhs_params = self.process_lhs(compiler, connection)
|
|
||||||
rhs, rhs_params = self.process_rhs(compiler, connection)
|
|
||||||
sql_template = connection.ops.fulltext_search_sql(field_name=lhs)
|
|
||||||
return sql_template, lhs_params + rhs_params
|
|
||||||
|
|
||||||
|
|
||||||
@Field.register_lookup
|
@Field.register_lookup
|
||||||
class Regex(BuiltinLookup):
|
class Regex(BuiltinLookup):
|
||||||
lookup_name = 'regex'
|
lookup_name = 'regex'
|
||||||
|
@ -2918,33 +2918,6 @@ SQL equivalent::
|
|||||||
|
|
||||||
SELECT ... WHERE pub_date IS NULL;
|
SELECT ... WHERE pub_date IS NULL;
|
||||||
|
|
||||||
.. fieldlookup:: search
|
|
||||||
|
|
||||||
``search``
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 1.10
|
|
||||||
|
|
||||||
See :ref:`the 1.10 release notes <search-lookup-replacement>` for how to
|
|
||||||
replace it.
|
|
||||||
|
|
||||||
A boolean full-text search, taking advantage of full-text indexing. This is
|
|
||||||
like :lookup:`contains` but is significantly faster due to full-text indexing.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
Entry.objects.filter(headline__search="+Django -jazz Python")
|
|
||||||
|
|
||||||
SQL equivalent::
|
|
||||||
|
|
||||||
SELECT ... WHERE MATCH(tablename, headline) AGAINST (+Django -jazz Python IN BOOLEAN MODE);
|
|
||||||
|
|
||||||
Note this is only available in MySQL and requires direct manipulation of the
|
|
||||||
database to add the full-text index. By default Django uses BOOLEAN MODE for
|
|
||||||
full text searches. See the `MySQL documentation`_ for additional details.
|
|
||||||
|
|
||||||
.. _MySQL documentation: https://dev.mysql.com/doc/refman/en/fulltext-boolean.html
|
|
||||||
|
|
||||||
.. fieldlookup:: regex
|
.. fieldlookup:: regex
|
||||||
|
|
||||||
``regex``
|
``regex``
|
||||||
|
@ -353,3 +353,5 @@ these features.
|
|||||||
|
|
||||||
* Support for query lookups using the model name when
|
* Support for query lookups using the model name when
|
||||||
``Meta.default_related_name`` is set is removed.
|
``Meta.default_related_name`` is set is removed.
|
||||||
|
|
||||||
|
* The MySQL ``__search`` lookup is removed.
|
||||||
|
@ -75,19 +75,6 @@ class Player(models.Model):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
# To test __search lookup a fulltext index is needed. This
|
|
||||||
# is only available when using MySQL 5.6, or when using MyISAM
|
|
||||||
# tables. As 5.6 isn't common yet, lets use MyISAM table for
|
|
||||||
# testing. The table is manually created by the test method.
|
|
||||||
# RemovedInDjango20Warning
|
|
||||||
class MyISAMArticle(models.Model):
|
|
||||||
headline = models.CharField(max_length=100)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
db_table = 'myisam_article'
|
|
||||||
managed = False
|
|
||||||
|
|
||||||
|
|
||||||
class Product(models.Model):
|
class Product(models.Model):
|
||||||
name = models.CharField(max_length=80)
|
name = models.CharField(max_length=80)
|
||||||
qty_target = models.DecimalField(max_digits=6, decimal_places=2)
|
qty_target = models.DecimalField(max_digits=6, decimal_places=2)
|
||||||
|
@ -3,16 +3,11 @@ from __future__ import unicode_literals
|
|||||||
import collections
|
import collections
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from unittest import skipUnless
|
|
||||||
|
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db import connection
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
from django.test import (
|
|
||||||
TestCase, TransactionTestCase, ignore_warnings, skipUnlessDBFeature,
|
|
||||||
)
|
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
|
||||||
|
|
||||||
from .models import Article, Author, Game, MyISAMArticle, Player, Season, Tag
|
from .models import Article, Author, Game, Player, Season, Tag
|
||||||
|
|
||||||
|
|
||||||
class LookupTests(TestCase):
|
class LookupTests(TestCase):
|
||||||
@ -775,26 +770,3 @@ class LookupTests(TestCase):
|
|||||||
'<Article: Article 7>'],
|
'<Article: Article 7>'],
|
||||||
ordered=False
|
ordered=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class LookupTransactionTests(TransactionTestCase):
|
|
||||||
available_apps = ['lookup']
|
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango20Warning)
|
|
||||||
@skipUnless(connection.vendor == 'mysql', 'requires MySQL')
|
|
||||||
def test_mysql_lookup_search(self):
|
|
||||||
# To use fulltext indexes on MySQL either version 5.6 is needed, or one must use
|
|
||||||
# MyISAM tables. Neither of these combinations is currently available on CI, so
|
|
||||||
# lets manually create a MyISAM table for Article model.
|
|
||||||
with connection.cursor() as cursor:
|
|
||||||
cursor.execute(
|
|
||||||
"CREATE TEMPORARY TABLE myisam_article ("
|
|
||||||
" id INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
|
||||||
" headline VARCHAR(100) NOT NULL "
|
|
||||||
") ENGINE MYISAM")
|
|
||||||
dr = MyISAMArticle.objects.create(headline='Django Reinhardt')
|
|
||||||
MyISAMArticle.objects.create(headline='Ringo Star')
|
|
||||||
# NOTE: Needs to be created after the article has been saved.
|
|
||||||
cursor.execute(
|
|
||||||
'CREATE FULLTEXT INDEX myisam_article_ft ON myisam_article (headline)')
|
|
||||||
self.assertSequenceEqual(MyISAMArticle.objects.filter(headline__search='Reinhardt'), [dr])
|
|
||||||
|
Loading…
Reference in New Issue
Block a user