Комната выдает ошибку: в предварительно упакованной базе данных неверная схема для таблицы FTS - PullRequest
1 голос
/ 09 ноября 2019

Я разрабатываю приложение для словаря, которое обеспечивает поиск по таблице FTS. Определения взяты из предварительно упакованной базы данных, которая имеет следующую схему: (вывод .schema из программы sqlite3 в Linux)

sqlite> .open words.db
sqlite> .schema
CREATE TABLE entries
    (id INTEGER PRIMARY KEY NOT NULL,
    word TEXT NOT NULL COLLATE NOCASE,
    wordtype TEXT NOT NULL COLLATE NOCASE,
    definition TEXT NOT NULL COLLATE NOCASE);
CREATE INDEX words_index ON entries(id, word);
CREATE VIRTUAL TABLE entriesFts USING FTS4(content='entries', word)
/* entriesFts(word) */;
CREATE TABLE IF NOT EXISTS 'entriesFts_segments'(blockid INTEGER PRIMARY KEY, block BLOB);
CREATE TABLE IF NOT EXISTS 'entriesFts_segdir'(level INTEGER,idx INTEGER,start_block INTEGER,leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx));
CREATE TABLE IF NOT EXISTS 'entriesFts_docsize'(docid INTEGER PRIMARY KEY, size BLOB);
CREATE TABLE IF NOT EXISTS 'entriesFts_stat'(id INTEGER PRIMARY KEY, value BLOB);

И мои определения сущностей выглядят так:

@Entity(tableName="entries",
    indices = [Index(name = "words_index", value = ["id", "word"])])
data class Word (
    @PrimaryKey val id :Int,
    @ColumnInfo val word :String,
    @ColumnInfo(name = "wordtype") val wordType :String,
    @ColumnInfo val definition :String
)

/* Used when displaying list of words */
@Fts4(contentEntity = Word::class)
@Entity(tableName = "entriesFts")
data class WordMinimal (
    @PrimaryKey @ColumnInfo(name = "rowid") val id :Int,
    @ColumnInfo val word :String
)

Мне кажется, что схемы идеально совпадают, но у Room другое мнение: /
Выдает эту ошибку в logcat:

java.lang.IllegalStateException: Pre-packaged database has an invalid schema: entriesFts(rawderm.dictionary.en.db.WordMinimal).
     Expected:
    FtsTableInfo{name='entriesFts', columns=[word], options=[content=`entries`]}
     Found:
    FtsTableInfo{name='entriesFts', columns=[word], options=[content='entries']}

1 Ответ

2 голосов
/ 10 ноября 2019

Номер довольно специфичен в отношении символов, используемых для включения имен, и в основном принимает только серьезные акценты ` (код ASCII 96) для вложения имен столбцов.

Самый безопасный способ кодировать столбцы - этоиспользовать серьезные акценты, как это делает Room. Сказать, что самый простой способ получить точные схемы - позволить Room сгенерировать код схемы от вашего имени.

Вы можете сделать это, создав сущность (и), а также класс Database (т.е. класс, расширяющий Room Database). ) затем компилируем (Ctrl + F9) и затем ищем в сгенерированном коде код, который является именем класса базы данных, к которому добавляется _Impl. В этом классе будет метод createAllTables . Он содержит SQL для таблиц, которые Room ожидает , что соответствует сущности.

Поскольку такая комната удобно генерирует: -

    _db.execSQL("CREATE TABLE IF NOT EXISTS `entries` (`id` INTEGER NOT NULL, `word` TEXT NOT NULL, `wordtype` TEXT NOT NULL, `definition` TEXT NOT NULL, PRIMARY KEY(`id`))");
    _db.execSQL("CREATE INDEX IF NOT EXISTS `words_index` ON `entries` (`id`, `word`)");
    _db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `entriesFts` USING FTS4(`word` TEXT NOT NULL, content=`entries`)");
    _db.execSQL("CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_entriesFts_BEFORE_UPDATE BEFORE UPDATE ON `entries` BEGIN DELETE FROM `entriesFts` WHERE `docid`=OLD.`rowid`; END");
    _db.execSQL("CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_entriesFts_BEFORE_DELETE BEFORE DELETE ON `entries` BEGIN DELETE FROM `entriesFts` WHERE `docid`=OLD.`rowid`; END");
    _db.execSQL("CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_entriesFts_AFTER_UPDATE AFTER UPDATE ON `entries` BEGIN INSERT INTO `entriesFts`(`docid`, `word`) VALUES (NEW.`rowid`, NEW.`word`); END");
    _db.execSQL("CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_entriesFts_AFTER_INSERT AFTER INSERT ON `entries` BEGIN INSERT INTO `entriesFts`(`docid`, `word`) VALUES (NEW.`rowid`, NEW.`word`); END");
  • Уведомлениекак это дополнительно создает триггеры для поддержания FTS. И что их не нужно указывать как или в сущностях (т. Е. У вас могут быть компоненты SQLite, которые не существуют как сущности, и Room не обнаруживает несоответствия).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...