kopia lustrzana https://github.com/wagtail/wagtail
Test for presence of fts5 extension in sqlite backend initialisation and migration
rodzic
cc90ec62b7
commit
4248d406c0
|
@ -12,14 +12,13 @@ def SearchBackend(params):
|
|||
from .mysql.mysql import MySQLSearchBackend
|
||||
return MySQLSearchBackend(params)
|
||||
elif connection.vendor == 'sqlite':
|
||||
import sqlite3
|
||||
if sqlite3.sqlite_version_info < (3, 19, 0):
|
||||
# Prior to version 3.19, SQLite doesn't support FTS5 queries with column filters ('{column_1 column_2} : query'), so we need to fall back to the dummy fallback backend.
|
||||
from .fallback import DatabaseSearchBackend
|
||||
return DatabaseSearchBackend(params)
|
||||
else:
|
||||
from .sqlite.utils import fts5_available
|
||||
if fts5_available():
|
||||
from .sqlite.sqlite import SQLiteSearchBackend
|
||||
return SQLiteSearchBackend(params)
|
||||
else:
|
||||
from .fallback import DatabaseSearchBackend
|
||||
return DatabaseSearchBackend(params)
|
||||
else:
|
||||
from .fallback import DatabaseSearchBackend
|
||||
return DatabaseSearchBackend(params)
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import sqlite3
|
||||
|
||||
from django.db import OperationalError
|
||||
|
||||
|
||||
def fts5_available():
|
||||
# based on https://stackoverflow.com/a/36656216/1853523
|
||||
if sqlite3.sqlite_version_info < (3, 19, 0):
|
||||
# Prior to version 3.19, SQLite doesn't support FTS5 queries with
|
||||
# column filters ('{column_1 column_2} : query'), which the sqlite
|
||||
# fulltext backend needs
|
||||
return False
|
||||
|
||||
tmp_db = sqlite3.connect(':memory:')
|
||||
try:
|
||||
tmp_db.execute('CREATE VIRTUAL TABLE fts5test USING fts5 (data);')
|
||||
except OperationalError:
|
||||
return False
|
||||
finally:
|
||||
tmp_db.close()
|
||||
|
||||
return True
|
|
@ -47,6 +47,8 @@ class Migration(migrations.Migration):
|
|||
]
|
||||
|
||||
elif connection.vendor == 'sqlite':
|
||||
from wagtail.search.backends.database.sqlite.utils import fts5_available
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='indexentry',
|
||||
|
@ -63,25 +65,29 @@ class Migration(migrations.Migration):
|
|||
name='title',
|
||||
field=models.TextField(),
|
||||
),
|
||||
migrations.SeparateDatabaseAndState(state_operations=[
|
||||
migrations.CreateModel(
|
||||
name='sqliteftsindexentry',
|
||||
fields=[
|
||||
('index_entry', models.OneToOneField(primary_key=True, serialize=False, to='wagtailsearch.indexentry', on_delete=models.CASCADE, db_column='rowid')),
|
||||
('title', models.TextField()),
|
||||
('body', models.TextField(null=True)),
|
||||
('autocomplete', models.TextField(null=True)),
|
||||
],
|
||||
options={'db_table': '%s_fts' % IndexEntry._meta.db_table},
|
||||
),
|
||||
], database_operations=[
|
||||
migrations.RunSQL(sql=('CREATE VIRTUAL TABLE %s_fts USING fts5(autocomplete, body, title)' % IndexEntry._meta.db_table), reverse_sql=('DROP TABLE %s_fts' % IndexEntry._meta.db_table)),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER insert_wagtailsearch_indexentry_fts AFTER INSERT ON %s BEGIN INSERT INTO %s_fts(title, body, autocomplete, rowid) VALUES (NEW.title, NEW.body, NEW.autocomplete, NEW.id); END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER insert_wagtailsearch_indexentry_fts')),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER update_wagtailsearch_indexentry_fts AFTER UPDATE ON %s BEGIN UPDATE %s_fts SET title=NEW.title, body=NEW.body, autocomplete=NEW.autocomplete WHERE rowid=NEW.id; END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER update_wagtailsearch_indexentry_fts')),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER delete_wagtailsearch_indexentry_fts AFTER DELETE ON %s BEGIN DELETE FROM %s_fts WHERE rowid=OLD.id; END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER delete_wagtailsearch_indexentry_fts'))
|
||||
])
|
||||
]
|
||||
|
||||
if fts5_available():
|
||||
operations.append(
|
||||
migrations.SeparateDatabaseAndState(state_operations=[
|
||||
migrations.CreateModel(
|
||||
name='sqliteftsindexentry',
|
||||
fields=[
|
||||
('index_entry', models.OneToOneField(primary_key=True, serialize=False, to='wagtailsearch.indexentry', on_delete=models.CASCADE, db_column='rowid')),
|
||||
('title', models.TextField()),
|
||||
('body', models.TextField(null=True)),
|
||||
('autocomplete', models.TextField(null=True)),
|
||||
],
|
||||
options={'db_table': '%s_fts' % IndexEntry._meta.db_table},
|
||||
),
|
||||
], database_operations=[
|
||||
migrations.RunSQL(sql=('CREATE VIRTUAL TABLE %s_fts USING fts5(autocomplete, body, title)' % IndexEntry._meta.db_table), reverse_sql=('DROP TABLE %s_fts' % IndexEntry._meta.db_table)),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER insert_wagtailsearch_indexentry_fts AFTER INSERT ON %s BEGIN INSERT INTO %s_fts(title, body, autocomplete, rowid) VALUES (NEW.title, NEW.body, NEW.autocomplete, NEW.id); END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER insert_wagtailsearch_indexentry_fts')),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER update_wagtailsearch_indexentry_fts AFTER UPDATE ON %s BEGIN UPDATE %s_fts SET title=NEW.title, body=NEW.body, autocomplete=NEW.autocomplete WHERE rowid=NEW.id; END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER update_wagtailsearch_indexentry_fts')),
|
||||
migrations.RunSQL(sql=('CREATE TRIGGER delete_wagtailsearch_indexentry_fts AFTER DELETE ON %s BEGIN DELETE FROM %s_fts WHERE rowid=OLD.id; END' % (IndexEntry._meta.db_table, IndexEntry._meta.db_table)), reverse_sql=('DROP TRIGGER delete_wagtailsearch_indexentry_fts'))
|
||||
])
|
||||
)
|
||||
|
||||
elif connection.vendor == 'mysql':
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
|
|
|
@ -195,6 +195,7 @@ if connection.vendor == 'postgresql':
|
|||
AbstractIndexEntry = AbstractPostgresIndexEntry
|
||||
|
||||
elif connection.vendor == 'sqlite':
|
||||
from wagtail.search.backends.database.sqlite.utils import fts5_available
|
||||
|
||||
class AbstractSQLiteIndexEntry(BaseIndexEntry):
|
||||
"""
|
||||
|
@ -210,14 +211,15 @@ elif connection.vendor == 'sqlite':
|
|||
|
||||
AbstractIndexEntry = AbstractSQLiteIndexEntry
|
||||
|
||||
class SQLiteFTSIndexEntry(models.Model):
|
||||
autocomplete = TextField(null=True)
|
||||
title = TextField(null=False)
|
||||
body = TextField(null=True)
|
||||
index_entry = OneToOneField(primary_key=True, to='wagtailsearch.indexentry', on_delete=models.CASCADE, db_column='rowid')
|
||||
if fts5_available():
|
||||
class SQLiteFTSIndexEntry(models.Model):
|
||||
autocomplete = TextField(null=True)
|
||||
title = TextField(null=False)
|
||||
body = TextField(null=True)
|
||||
index_entry = OneToOneField(primary_key=True, to='wagtailsearch.indexentry', on_delete=models.CASCADE, db_column='rowid')
|
||||
|
||||
class Meta:
|
||||
db_table = "wagtailsearch_indexentry_fts"
|
||||
class Meta:
|
||||
db_table = "wagtailsearch_indexentry_fts"
|
||||
|
||||
elif connection.vendor == 'mysql':
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue