mirror of
https://github.com/tnodir/fort
synced 2024-11-15 08:35:08 +00:00
UI: ConfManager: Add "app_fts" table for full-text search
This commit is contained in:
parent
787718a07e
commit
db3a2b4aa4
8
src/3rdparty/sqlite/sqlite_cfg.h
vendored
8
src/3rdparty/sqlite/sqlite_cfg.h
vendored
@ -31,12 +31,12 @@
|
||||
#define HAVE_MALLOC_USABLE_SIZE 1
|
||||
#define HAVE_ISNAN 1
|
||||
|
||||
//#define SQLITE_ENABLE_FTS5 1
|
||||
#define SQLITE_ENABLE_FTS5 1
|
||||
//#define SQLITE_ENABLE_JSON1 1
|
||||
#define SQLITE_ENABLE_MEMORY_MANAGEMENT 1
|
||||
//#define SQLITE_ENABLE_NULL_TRIM 1
|
||||
//#define SQLITE_ENABLE_PREUPDATE_HOOK 1
|
||||
//#define SQLITE_ENABLE_SESSION 1
|
||||
#define SQLITE_ENABLE_SESSION 1
|
||||
#define SQLITE_ENABLE_STAT4 1
|
||||
//#define SQLITE_ENABLE_UNLOCK_NOTIFY 1
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
#define SQLITE_OMIT_AUTOINIT 1
|
||||
#define SQLITE_OMIT_AUTOMATIC_INDEX 1
|
||||
#define SQLITE_OMIT_AUTORESET 1
|
||||
#define SQLITE_OMIT_BLOB_LITERAL 1
|
||||
//#define SQLITE_OMIT_BLOB_LITERAL 1
|
||||
#define SQLITE_OMIT_CAST 1
|
||||
#define SQLITE_OMIT_CHECK 1
|
||||
#define SQLITE_OMIT_COMPLETE 1
|
||||
@ -71,7 +71,7 @@
|
||||
#define SQLITE_OMIT_EXPLAIN 1
|
||||
#define SQLITE_OMIT_FOREIGN_KEY 1
|
||||
#define SQLITE_OMIT_GET_TABLE 1
|
||||
#define SQLITE_OMIT_INCRBLOB 1
|
||||
//#define SQLITE_OMIT_INCRBLOB 1
|
||||
#define SQLITE_OMIT_INTEGRITY_CHECK 1
|
||||
#define SQLITE_OMIT_JSON 1
|
||||
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
|
97
src/ui/3rdparty/sqlite/sqlitedb.cpp
vendored
97
src/ui/3rdparty/sqlite/sqlitedb.cpp
vendored
@ -19,6 +19,8 @@ const char *const defaultSqlPragmas = "PRAGMA journal_mode = WAL;"
|
||||
"PRAGMA synchronous = NORMAL;"
|
||||
"PRAGMA encoding = 'UTF-8';";
|
||||
|
||||
const QString ftsTableSuffix = "_fts";
|
||||
|
||||
QAtomicInt g_sqliteInitCount;
|
||||
|
||||
bool removeDbFile(const QString &filePath)
|
||||
@ -45,6 +47,12 @@ bool renameDbFile(const QString &filePath, const QString &newFilePath)
|
||||
return true;
|
||||
}
|
||||
|
||||
QString makeTriggerColumnNames(
|
||||
const QString &rowIdName, const QStringList &columnNames, const QString &prefix)
|
||||
{
|
||||
return (prefix + rowIdName) + (',' + prefix) + columnNames.join(',' + prefix);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SqliteDb::SqliteDb(const QString &filePath, quint32 openFlags) :
|
||||
@ -248,6 +256,11 @@ bool SqliteDb::setBusyTimeoutMs(int v)
|
||||
return sqlite3_busy_timeout(m_db, v) == SQLITE_OK;
|
||||
}
|
||||
|
||||
QString SqliteDb::getFtsTableName(const QString &tableName)
|
||||
{
|
||||
return tableName + ftsTableSuffix;
|
||||
}
|
||||
|
||||
QString SqliteDb::migrationOldSchemaName()
|
||||
{
|
||||
return QLatin1String("old");
|
||||
@ -269,8 +282,10 @@ QStringList SqliteDb::tableNames(const QString &schemaName)
|
||||
|
||||
const auto masterTable = entityName(schemaName, "sqlite_master");
|
||||
const auto sql = QString("SELECT name FROM %1"
|
||||
" WHERE type = 'table' AND name NOT LIKE 'sqlite_%';")
|
||||
.arg(masterTable);
|
||||
" WHERE type = 'table'"
|
||||
" AND name NOT LIKE 'sqlite_%'"
|
||||
" AND name NOT LIKE '%%2_%';")
|
||||
.arg(masterTable, ftsTableSuffix);
|
||||
|
||||
SqliteStmt stmt;
|
||||
if (stmt.prepare(db(), sql.toLatin1())) {
|
||||
@ -353,14 +368,14 @@ bool SqliteDb::migrateDb(const MigrateOptions &opt, int userVersion, bool isNewD
|
||||
}
|
||||
|
||||
// Run migration SQL scripts
|
||||
bool success = migrateSqlScripts(opt, userVersion, isNewDb);
|
||||
if (!migrateSqlScripts(opt, userVersion, isNewDb))
|
||||
return false;
|
||||
|
||||
// Re-create the DB: End
|
||||
if (success && opt.recreate) {
|
||||
success = importBackup(opt);
|
||||
}
|
||||
if (opt.recreate && !(createFtsTables(opt) && importBackup(opt)))
|
||||
return false;
|
||||
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqliteDb::migrateSqlScripts(const MigrateOptions &opt, int userVersion, bool isNewDb)
|
||||
@ -415,6 +430,74 @@ bool SqliteDb::migrateSqlScripts(const MigrateOptions &opt, int userVersion, boo
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SqliteDb::createFtsTables(const MigrateOptions &opt)
|
||||
{
|
||||
if (opt.ftsTables.isEmpty())
|
||||
return true;
|
||||
|
||||
bool success = true;
|
||||
|
||||
beginTransaction();
|
||||
|
||||
for (const FtsTable &ftsTable : opt.ftsTables) {
|
||||
beginSavepoint();
|
||||
|
||||
success = createFtsTable(ftsTable);
|
||||
|
||||
if (success) {
|
||||
releaseSavepoint();
|
||||
} else {
|
||||
qCCritical(LC) << "FTS error:" << ftsTable.contentTable << errorMessage();
|
||||
rollbackSavepoint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
commitTransaction();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SqliteDb::createFtsTable(const FtsTable &ftsTable)
|
||||
{
|
||||
/*
|
||||
* %1: content table name
|
||||
* %2: fts table name
|
||||
* %3: content rowid column name
|
||||
* %4: content column names list
|
||||
* %5: triggered new column names list (new.*)
|
||||
* %6: triggered old column names list (old.*)
|
||||
*/
|
||||
static const char *const ftsCreateSql =
|
||||
"CREATE VIRTUAL TABLE %2 USING fts5(%4, content='%1', content_rowid='%3');"
|
||||
"CREATE TRIGGER %2_ai AFTER INSERT ON %1 BEGIN"
|
||||
" INSERT INTO %2(rowid, %4) VALUES (%5);"
|
||||
"END;"
|
||||
"CREATE TRIGGER %2_ad AFTER DELETE ON %1 BEGIN"
|
||||
" INSERT INTO %2(%2, rowid, %4) VALUES('delete', %6);"
|
||||
"END;"
|
||||
"CREATE TRIGGER %2_au AFTER UPDATE ON %1 BEGIN"
|
||||
" INSERT INTO %2(%2, rowid, %4) VALUES('delete', %6);"
|
||||
" INSERT INTO %2(rowid, %4) VALUES (%5);"
|
||||
"END;";
|
||||
|
||||
const auto contentTableName = ftsTable.contentTable;
|
||||
const auto ftsTableName = getFtsTableName(contentTableName);
|
||||
const auto contentRowidName = ftsTable.contentRowid;
|
||||
const auto contentColumnNames = ftsTable.columns.join(',');
|
||||
const auto newTriggerColumnNames =
|
||||
makeTriggerColumnNames(contentRowidName, ftsTable.columns, "new.");
|
||||
const auto oldTriggerColumnNames =
|
||||
makeTriggerColumnNames(contentRowidName, ftsTable.columns, "old.");
|
||||
|
||||
const auto sql =
|
||||
QString(ftsCreateSql)
|
||||
.arg(contentTableName, ftsTableName, contentRowidName, contentColumnNames,
|
||||
newTriggerColumnNames, oldTriggerColumnNames);
|
||||
|
||||
return executeStr(sql);
|
||||
}
|
||||
|
||||
bool SqliteDb::clearWithBackup(const char *sqlPragmas)
|
||||
{
|
||||
const QString oldEncoding = this->encoding();
|
||||
|
13
src/ui/3rdparty/sqlite/sqlitedb.h
vendored
13
src/ui/3rdparty/sqlite/sqlitedb.h
vendored
@ -33,6 +33,13 @@ public:
|
||||
OpenDefaultReadWrite = (OpenReadWrite | OpenCreate | OpenNoMutex)
|
||||
};
|
||||
|
||||
struct FtsTable
|
||||
{
|
||||
const QString contentTable;
|
||||
const QString contentRowid;
|
||||
const QStringList columns;
|
||||
};
|
||||
|
||||
struct MigrateOptions
|
||||
{
|
||||
const QString sqlDir;
|
||||
@ -43,6 +50,7 @@ public:
|
||||
bool autoCopyTables = true;
|
||||
SQLITEDB_MIGRATE_FUNC migrateFunc = nullptr;
|
||||
void *migrateContext = nullptr;
|
||||
QVector<FtsTable> ftsTables;
|
||||
};
|
||||
|
||||
explicit SqliteDb(
|
||||
@ -99,6 +107,8 @@ public:
|
||||
|
||||
bool setBusyTimeoutMs(int v);
|
||||
|
||||
static QString getFtsTableName(const QString &tableName);
|
||||
|
||||
static QString migrationOldSchemaName();
|
||||
static QString migrationNewSchemaName();
|
||||
static QString entityName(const QString &schemaName, const QString &objectName);
|
||||
@ -114,6 +124,9 @@ private:
|
||||
bool migrateDb(const MigrateOptions &opt, int userVersion, bool isNewDb);
|
||||
bool migrateSqlScripts(const MigrateOptions &opt, int userVersion, bool isNewDb);
|
||||
|
||||
bool createFtsTables(const MigrateOptions &opt);
|
||||
bool createFtsTable(const FtsTable &ftsTable);
|
||||
|
||||
bool clearWithBackup(const char *sqlPragmas);
|
||||
bool importBackup(const MigrateOptions &opt);
|
||||
|
||||
|
@ -71,10 +71,12 @@ void AppInfoManager::setUp()
|
||||
return;
|
||||
}
|
||||
|
||||
SqliteDb::MigrateOptions opt = { .sqlDir = ":/appinfo/migrations",
|
||||
SqliteDb::MigrateOptions opt = {
|
||||
.sqlDir = ":/appinfo/migrations",
|
||||
.version = DATABASE_USER_VERSION,
|
||||
.recreate = true,
|
||||
.importOldData = false };
|
||||
.importOldData = false,
|
||||
};
|
||||
|
||||
if (!sqliteDb()->migrate(opt)) {
|
||||
qCCritical(LC) << "Migration error" << sqliteDb()->filePath();
|
||||
|
@ -37,7 +37,7 @@ namespace {
|
||||
|
||||
const QLoggingCategory LC("conf");
|
||||
|
||||
constexpr int DATABASE_USER_VERSION = 21;
|
||||
constexpr int DATABASE_USER_VERSION = 22;
|
||||
|
||||
constexpr int APP_END_TIMER_INTERVAL_MIN = 100;
|
||||
constexpr int APP_END_TIMER_INTERVAL_MAX = 24 * 60 * 60 * 1000; // 1 day
|
||||
@ -536,10 +536,19 @@ void ConfManager::setUp()
|
||||
return;
|
||||
}
|
||||
|
||||
SqliteDb::MigrateOptions opt = { .sqlDir = ":/conf/migrations",
|
||||
SqliteDb::MigrateOptions opt = {
|
||||
.sqlDir = ":/conf/migrations",
|
||||
.version = DATABASE_USER_VERSION,
|
||||
.recreate = true,
|
||||
.migrateFunc = &migrateFunc };
|
||||
.migrateFunc = &migrateFunc,
|
||||
.ftsTables = {
|
||||
{
|
||||
.contentTable = "app",
|
||||
.contentRowid = "app_id",
|
||||
.columns = { "path", "name" }
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (!sqliteDb()->migrate(opt)) {
|
||||
qCCritical(LC) << "Migration error" << sqliteDb()->filePath();
|
||||
|
@ -81,10 +81,12 @@ void StatManager::setUp()
|
||||
return;
|
||||
}
|
||||
|
||||
SqliteDb::MigrateOptions opt = { .sqlDir = ":/stat/migrations/traf",
|
||||
SqliteDb::MigrateOptions opt = {
|
||||
.sqlDir = ":/stat/migrations/traf",
|
||||
.version = DATABASE_USER_VERSION,
|
||||
.recreate = true,
|
||||
.migrateFunc = &migrateFunc };
|
||||
.migrateFunc = &migrateFunc,
|
||||
};
|
||||
|
||||
if (!sqliteDb()->migrate(opt)) {
|
||||
qCCritical(LC) << "Migration error" << sqliteDb()->filePath();
|
||||
|
Loading…
Reference in New Issue
Block a user