Skip to content

Commit e5d40e5

Browse files
committed
Avoid indexing search_names on MySQL
1 parent 359f15a commit e5d40e5

File tree

3 files changed

+26
-36
lines changed

3 files changed

+26
-36
lines changed

cities_light/migrations/0003_auto__add_field_city_search_names.py

+9-33
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,18 @@
44
from south.v2 import SchemaMigration
55
from django.db import models
66

7-
class Migration(SchemaMigration):
8-
9-
def forwards(self, orm):
10-
if not db.dry_run:
11-
print """
12-
13-
BIG FAT WARNING
14-
15-
This migration adds a TextField (search_names), with an index.
16-
MySQL does not support indexing TEXT/BLOB columns.
17-
18-
On MySQL, this migration should fail like:
19-
20-
FATAL ERROR - The following SQL query failed: CREATE INDEX `cities_light_city_cd532746` ON `cities_light_city` (`search_names`);
21-
The error was: (1170, "BLOB/TEXT column 'search_names' used in key specification without a key length")
7+
from cities_light.settings import INDEX_SEARCH_NAMES
228

23-
Since the search_names column should be created anyway, you can get
24-
past this with:
9+
if INDEX_SEARCH_NAMES:
10+
INDEX_SEARCH_NAMES_STRING = 'True'
11+
else:
12+
INDEX_SEARCH_NAMES_STRING = 'False'
2513

26-
./manage.py migrate cities_light --fake 0003
27-
# continue migrating
28-
./manage.py migrate cities_light
29-
30-
31-
If you can think of any better solution, please report it to
32-
GitHub's project page:
33-
34-
https://github.com/yourlabs/django-cities-light/issues/
35-
36-
37-
If you are on anything else than MySQL, you can ignore this message
38-
and enjoy indexing on search_names.
39-
"""
14+
class Migration(SchemaMigration):
4015

16+
def forwards(self, orm):
4117
# Adding field 'City.search_names'
42-
db.add_column('cities_light_city', 'search_names', self.gf('django.db.models.fields.TextField')(default='', max_length=4000, db_index=True, blank=True), keep_default=False)
18+
db.add_column('cities_light_city', 'search_names', self.gf('django.db.models.fields.TextField')(default='', max_length=4000, db_index=INDEX_SEARCH_NAMES, blank=True), keep_default=False)
4319

4420

4521
def backwards(self, orm):
@@ -58,7 +34,7 @@ def backwards(self, orm):
5834
'longitude': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '5', 'blank': 'True'}),
5935
'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'db_index': 'True'}),
6036
'name_ascii': ('django.db.models.fields.CharField', [], {'max_length': '200', 'db_index': 'True'}),
61-
'search_names': ('django.db.models.fields.TextField', [], {'default': "''", 'max_length': '4000', 'db_index': 'True', 'blank': 'True'}),
37+
'search_names': ('django.db.models.fields.TextField', [], {'default': "''", 'max_length': '4000', 'db_index': INDEX_SEARCH_NAMES_STRING, 'blank': 'True'}),
6238
'slug': ('autoslug.fields.AutoSlugField', [], {'unique_with': '()', 'max_length': '50', 'populate_from': 'None', 'db_index': 'True'})
6339
},
6440
'cities_light.country': {

cities_light/models.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ class City(Base):
158158
name = models.CharField(max_length=200, db_index=True)
159159
display_name = models.CharField(max_length=200)
160160

161-
search_names = ToSearchTextField(max_length=4000, db_index=True,
162-
blank=True, default='')
161+
search_names = ToSearchTextField(max_length=4000,
162+
db_index=INDEX_SEARCH_NAMES, blank=True, default='')
163163

164164
latitude = models.DecimalField(max_digits=8, decimal_places=5,
165165
null=True, blank=True)

cities_light/settings.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,20 @@
3939
DATA_DIR
4040
Absolute path to download and extract data into. Default is
4141
cities_light/data. Overridable in settings.CITIES_LIGHT_DATA_DIR
42+
43+
INDEX_SEARCH_NAMES
44+
If your database engine for cities_light supports indexing TextFields (ie.
45+
it is **not** MySQL), then this should be set to True. You might have to
46+
override this setting if using several databases for your project.
4247
"""
4348

4449
import os.path
4550

4651
from django.conf import settings
4752

4853
__all__ = ['COUNTRY_SOURCES', 'REGION_SOURCES', 'CITY_SOURCES',
49-
'TRANSLATION_LANGUAGES', 'TRANSLATION_SOURCES', 'SOURCES', 'DATA_DIR']
54+
'TRANSLATION_LANGUAGES', 'TRANSLATION_SOURCES', 'SOURCES', 'DATA_DIR',
55+
'INDEX_SEARCH_NAMES',]
5056

5157
COUNTRY_SOURCES = getattr(settings, 'CITIES_LIGHT_COUNTRY_SOURCES',
5258
['http://download.geonames.org/export/dump/countryInfo.txt'])
@@ -65,3 +71,11 @@
6571
DATA_DIR = getattr(settings, 'CITIES_LIGHT_DATA_DIR',
6672
os.path.normpath(os.path.join(
6773
os.path.dirname(os.path.realpath(__file__)), 'data')))
74+
75+
# MySQL doesn't support indexing TextFields
76+
INDEX_SEARCH_NAMES = getattr(settings, 'CITIES_LIGHT_INDEX_SEARCH_NAMES', None)
77+
if INDEX_SEARCH_NAMES is None:
78+
INDEX_SEARCH_NAMES = True
79+
for database in settings.DATABASES.values():
80+
if 'mysql' in database['ENGINE'].lower():
81+
INDEX_SEARCH_NAMES = False

0 commit comments

Comments
 (0)