diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp | 81 |
1 files changed, 56 insertions, 25 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp index 9bfb46f..b137c1f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb.cpp @@ -1,15 +1,13 @@ #include "abstractdb.h" -#include "services/dbmanager.h" +#include "services/collationmanager.h" #include "common/utils.h" #include "asyncqueryrunner.h" #include "sqlresultsrow.h" #include "common/utils_sql.h" -#include "services/config.h" #include "sqlerrorresults.h" #include "sqlerrorcodes.h" #include "services/notifymanager.h" #include "services/sqliteextensionmanager.h" -#include "log.h" #include "parser/lexer.h" #include "common/compatibility.h" #include <QDebug> @@ -25,10 +23,12 @@ quint32 AbstractDb::asyncId = 1; AbstractDb::AbstractDb(const QString& name, const QString& path, const QHash<QString, QVariant>& connOptions) : name(name), path(path), connOptions(connOptions) { + connect(SQLITESTUDIO, SIGNAL(aboutToQuit()), this, SLOT(appIsAboutToQuit())); } AbstractDb::~AbstractDb() { + disconnect(SQLITESTUDIO, SIGNAL(aboutToQuit()), this, SLOT(appIsAboutToQuit())); } bool AbstractDb::open() @@ -47,7 +47,11 @@ bool AbstractDb::close() if (deny) return false; - bool res = !isOpen() || closeQuiet(); + bool open = isOpen(); + if (open) + flushWal(); + + bool res = !open || closeQuiet(); if (res) emit disconnected(); @@ -71,7 +75,7 @@ bool AbstractDb::closeQuiet() registeredFunctions.clear(); registeredCollations.clear(); if (FUNCTIONS) // FUNCTIONS is already null when closing db while closing entire app - disconnect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerAllFunctions())); + disconnect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerUserFunctions())); return res; } @@ -89,40 +93,49 @@ bool AbstractDb::openForProbing() return res; } -void AbstractDb::registerAllFunctions() +void AbstractDb::registerUserFunctions() { - for (const RegisteredFunction& regFn : registeredFunctions) + QMutableSetIterator<RegisteredFunction> it(registeredFunctions); + while (it.hasNext()) { + const RegisteredFunction& regFn = it.next(); + if (regFn.builtIn) + continue; + if (!deregisterFunction(regFn.name, regFn.argCount)) qWarning() << "Failed to deregister custom SQL function:" << regFn.name; - } - registeredFunctions.clear(); + it.remove(); + } RegisteredFunction regFn; - for (FunctionManager::ScriptFunction* fnPtr : FUNCTIONS->getScriptFunctionsForDatabase(getName())) + for (FunctionManager::ScriptFunction*& fnPtr : FUNCTIONS->getScriptFunctionsForDatabase(getName())) { regFn.argCount = fnPtr->undefinedArgs ? -1 : fnPtr->arguments.count(); regFn.name = fnPtr->name; regFn.type = fnPtr->type; + regFn.deterministic = fnPtr->deterministic; registerFunction(regFn); } +} - for (FunctionManager::NativeFunction* fnPtr : FUNCTIONS->getAllNativeFunctions()) +void AbstractDb::registerBuiltInFunctions() +{ + RegisteredFunction regFn; + for (FunctionManager::NativeFunction*& fnPtr : FUNCTIONS->getAllNativeFunctions()) { regFn.argCount = fnPtr->undefinedArgs ? -1 : fnPtr->arguments.count(); regFn.name = fnPtr->name; regFn.type = fnPtr->type; + regFn.builtIn = true; + regFn.deterministic = fnPtr->deterministic; registerFunction(regFn); } - - disconnect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerAllFunctions())); - connect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerAllFunctions())); } -void AbstractDb::registerAllCollations() +void AbstractDb::registerUserCollations() { - for (const QString& name : registeredCollations) + for (QString& name : registeredCollations) { if (!deregisterCollation(name)) qWarning() << "Failed to deregister custom collation:" << name; @@ -130,16 +143,16 @@ void AbstractDb::registerAllCollations() registeredCollations.clear(); - for (const CollationManager::CollationPtr& collPtr : COLLATIONS->getCollationsForDatabase(getName())) + for (CollationManager::CollationPtr& collPtr : COLLATIONS->getCollationsForDatabase(getName())) registerCollation(collPtr->name); - disconnect(COLLATIONS, SIGNAL(collationListChanged()), this, SLOT(registerAllCollations())); - connect(COLLATIONS, SIGNAL(collationListChanged()), this, SLOT(registerAllCollations())); + disconnect(COLLATIONS, SIGNAL(collationListChanged()), this, SLOT(registerUserCollations())); + connect(COLLATIONS, SIGNAL(collationListChanged()), this, SLOT(registerUserCollations())); } void AbstractDb::loadExtensions() { - for (const SqliteExtensionManager::ExtensionPtr& extPtr : SQLITE_EXTENSIONS->getExtensionForDatabase(getName())) + for (SqliteExtensionManager::ExtensionPtr& extPtr : SQLITE_EXTENSIONS->getExtensionForDatabase(getName())) loadedExtensionCount += loadExtension(extPtr->filePath, extPtr->initFunc) ? 1 : 0; connect(SQLITE_EXTENSIONS, SIGNAL(extensionListChanged()), this, SLOT(reloadExtensions())); @@ -377,14 +390,20 @@ bool AbstractDb::openAndSetup() // Implementation specific initialization initAfterOpen(); + // Built-in SQL functions + registerBuiltInFunctions(); + // Load extension loadExtensions(); // Custom SQL functions - registerAllFunctions(); + registerUserFunctions(); // Custom collations - registerAllCollations(); + registerUserCollations(); + + disconnect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerUserFunctions())); + connect(FUNCTIONS, SIGNAL(functionListChanged()), this, SLOT(registerUserFunctions())); return result; } @@ -616,6 +635,12 @@ void AbstractDb::asyncQueryFinished(AsyncQueryRunner *runner) emit idle(); } +void AbstractDb::appIsAboutToQuit() +{ + if (isOpen()) + flushWal(); +} + QString AbstractDb::attach(Db* otherDb, bool silent) { QWriteLocker locker(&dbOperLock); @@ -716,7 +741,7 @@ QString AbstractDb::getUniqueNewObjectName(const QString &attachedDbName) QSet<QString> existingNames; SqlQueryPtr results = exec(QString("SELECT name FROM %1.sqlite_master").arg(dbName)); - for (SqlResultsRowPtr row : results->getAll()) + for (SqlResultsRowPtr& row : results->getAll()) existingNames << row->value(0).toString(); return randStrNotIn(16, existingNames, false); @@ -875,10 +900,10 @@ void AbstractDb::registerFunction(const AbstractDb::RegisteredFunction& function switch (function.type) { case FunctionManager::ScriptFunction::SCALAR: - successful = registerScalarFunction(function.name, function.argCount); + successful = registerScalarFunction(function.name, function.argCount, function.deterministic); break; case FunctionManager::ScriptFunction::AGGREGATE: - successful = registerAggregateFunction(function.name, function.argCount); + successful = registerAggregateFunction(function.name, function.argCount, function.deterministic); break; } @@ -888,6 +913,12 @@ void AbstractDb::registerFunction(const AbstractDb::RegisteredFunction& function qCritical() << "Could not register SQL function:" << function.name << function.argCount << function.type; } +void AbstractDb::flushWal() +{ + if (!flushWalInternal()) + notifyWarn(tr("Failed to make full WAL checkpoint on database '%1'. Error returned from SQLite engine: %2").arg(name, getErrorTextInternal())); +} + int qHash(const AbstractDb::RegisteredFunction& fn) { return qHash(fn.name) ^ fn.argCount ^ fn.type; |
