Room gives error: pre-packaged database has an invalid schema for FTS Table
Room gives error: pre-packaged database has an invalid schema for FTS Table
我正在开发一个字典应用程序,它使用 FTS table 提供搜索。
这些定义来自预先打包的数据库,它具有以下模式:(Linux 上的 sqlite3 程序的 .schema
的输出)
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']}
Room 对用于包围名称的字符非常特殊,基本上只接受重音符号 `(ASCII 码 96)用于包围列名称。
对列进行编码的最安全方法是使用重音符号,因为 Room 就是这样做的。说获得准确模式的最简单方法是让 Room 代表您生成模式代码。
您可以通过创建实体和数据库 class(即扩展 Room 数据库的 class)然后编译 (Ctrl + F9) 然后查看为数据库 class 名称附加 _Impl 的代码生成的代码。在那个 class 中会有一个 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 不会检测到不匹配)。
我正在开发一个字典应用程序,它使用 FTS table 提供搜索。
这些定义来自预先打包的数据库,它具有以下模式:(Linux 上的 sqlite3 程序的 .schema
的输出)
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']}
Room 对用于包围名称的字符非常特殊,基本上只接受重音符号 `(ASCII 码 96)用于包围列名称。
对列进行编码的最安全方法是使用重音符号,因为 Room 就是这样做的。说获得准确模式的最简单方法是让 Room 代表您生成模式代码。
您可以通过创建实体和数据库 class(即扩展 Room 数据库的 class)然后编译 (Ctrl + F9) 然后查看为数据库 class 名称附加 _Impl 的代码生成的代码。在那个 class 中会有一个 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 不会检测到不匹配)。