diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/sql | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/sql')
-rw-r--r-- | Source/WebCore/platform/sql/SQLValue.cpp | 56 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLValue.h | 28 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteAuthorizer.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteDatabase.cpp | 117 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteDatabase.h | 77 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp | 12 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteDatabaseTracker.h | 8 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteFileSystem.cpp | 41 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteFileSystem.h | 11 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteStatement.cpp | 96 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteStatement.h | 62 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteTransaction.cpp | 6 | ||||
-rw-r--r-- | Source/WebCore/platform/sql/SQLiteTransaction.h | 19 |
13 files changed, 194 insertions, 341 deletions
diff --git a/Source/WebCore/platform/sql/SQLValue.cpp b/Source/WebCore/platform/sql/SQLValue.cpp deleted file mode 100644 index b301ad28f..000000000 --- a/Source/WebCore/platform/sql/SQLValue.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following condition - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "SQLValue.h" - -namespace WebCore { - -SQLValue::SQLValue(const SQLValue& val) - : m_type(val.m_type) - , m_number(val.m_number) - , m_string(val.m_string.isolatedCopy()) -{ -} - -String SQLValue::string() const -{ - ASSERT(m_type == StringValue); - - // Must return a copy since ref-shared Strings are not thread safe - return m_string.isolatedCopy(); -} - -double SQLValue::number() const -{ - ASSERT(m_type == NumberValue); - - return m_number; -} - -} diff --git a/Source/WebCore/platform/sql/SQLValue.h b/Source/WebCore/platform/sql/SQLValue.h index 86ff887c1..d0ca03ca7 100644 --- a/Source/WebCore/platform/sql/SQLValue.h +++ b/Source/WebCore/platform/sql/SQLValue.h @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -26,33 +26,13 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLValue_h -#define SQLValue_h +#pragma once -#include <wtf/Threading.h> +#include <wtf/Variant.h> #include <wtf/text/WTFString.h> namespace WebCore { - class SQLValue { - public: - enum Type { NullValue, NumberValue, StringValue }; +using SQLValue = Variant<std::nullptr_t, String, double>; - SQLValue() : m_type(NullValue), m_number(0.0) { } - SQLValue(double number) : m_type(NumberValue), m_number(number) { } - SQLValue(const String& s) : m_type(StringValue), m_number(0.0), m_string(s) { } - SQLValue(const SQLValue&); - - Type type() const { return m_type; } - - String string() const; - double number() const; - - private: - Type m_type; - double m_number; - String m_string; - }; }; - -#endif diff --git a/Source/WebCore/platform/sql/SQLiteAuthorizer.cpp b/Source/WebCore/platform/sql/SQLiteAuthorizer.cpp index d47a44d8b..b7e60a040 100644 --- a/Source/WebCore/platform/sql/SQLiteAuthorizer.cpp +++ b/Source/WebCore/platform/sql/SQLiteAuthorizer.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * diff --git a/Source/WebCore/platform/sql/SQLiteDatabase.cpp b/Source/WebCore/platform/sql/SQLiteDatabase.cpp index bc83fdd83..d03dc0e49 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/Source/WebCore/platform/sql/SQLiteDatabase.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -31,6 +31,7 @@ #include "Logging.h" #include "SQLiteFileSystem.h" #include "SQLiteStatement.h" +#include <mutex> #include <sqlite3.h> #include <thread> #include <wtf/Threading.h> @@ -39,15 +40,6 @@ namespace WebCore { -const int SQLResultDone = SQLITE_DONE; -const int SQLResultError = SQLITE_ERROR; -const int SQLResultOk = SQLITE_OK; -const int SQLResultRow = SQLITE_ROW; -const int SQLResultSchema = SQLITE_SCHEMA; -const int SQLResultFull = SQLITE_FULL; -const int SQLResultInterrupt = SQLITE_INTERRUPT; -const int SQLResultConstraint = SQLITE_CONSTRAINT; - static const char notOpenErrorMessage[] = "database is not open"; static void unauthorizedSQLFunction(sqlite3_context *context, int, sqlite3_value **) @@ -57,19 +49,28 @@ static void unauthorizedSQLFunction(sqlite3_context *context, int, sqlite3_value sqlite3_result_error(context, errorMessage.utf8().data(), -1); } -SQLiteDatabase::SQLiteDatabase() - : m_db(0) - , m_pageSize(-1) - , m_transactionInProgress(false) - , m_sharable(false) - , m_openingThread(0) - , m_interrupted(false) - , m_openError(SQLITE_ERROR) - , m_openErrorMessage() - , m_lastChangesCount(0) +static void initializeSQLiteIfNecessary() { + static std::once_flag flag; + std::call_once(flag, [] { + // It should be safe to call this outside of std::call_once, since it is documented to be + // completely threadsafe. But in the past it was not safe, and the SQLite developers still + // aren't confident that it really is, and we still support ancient versions of SQLite. So + // std::call_once is used to stay on the safe side. See bug #143245. + int ret = sqlite3_initialize(); + if (ret != SQLITE_OK) { +#if SQLITE_VERSION_NUMBER >= 3007015 + WTFLogAlways("Failed to initialize SQLite: %s", sqlite3_errstr(ret)); +#else + WTFLogAlways("Failed to initialize SQLite"); +#endif + CRASH(); + } + }); } +SQLiteDatabase::SQLiteDatabase() = default; + SQLiteDatabase::~SQLiteDatabase() { close(); @@ -77,6 +78,8 @@ SQLiteDatabase::~SQLiteDatabase() bool SQLiteDatabase::open(const String& filename, bool forWebSQLDatabase) { + initializeSQLiteIfNecessary(); + close(); m_openError = SQLiteFileSystem::openDatabase(filename, &m_db, forWebSQLDatabase); @@ -109,17 +112,14 @@ bool SQLiteDatabase::open(const String& filename, bool forWebSQLDatabase) LOG_ERROR("SQLite database could not set temp_store to memory"); SQLiteStatement walStatement(*this, ASCIILiteral("PRAGMA journal_mode=WAL;")); - int result = walStatement.step(); - if (result != SQLITE_OK && result != SQLITE_ROW) - LOG_ERROR("SQLite database failed to set journal_mode to WAL, error: %s", lastErrorMsg()); - + if (walStatement.prepareAndStep() == SQLITE_ROW) { #ifndef NDEBUG - if (result == SQLITE_ROW) { String mode = walStatement.getColumnText(0); - if (!equalIgnoringCase(mode, "wal")) - LOG_ERROR("journal_mode of database should be 'wal', but is '%s'", mode.utf8().data()); - } + if (!equalLettersIgnoringASCIICase(mode, "wal")) + LOG_ERROR("journal_mode of database should be 'WAL', but is '%s'", mode.utf8().data()); #endif + } else + LOG_ERROR("SQLite database failed to set journal_mode to WAL, error: %s", lastErrorMsg()); return isOpen(); } @@ -131,7 +131,7 @@ void SQLiteDatabase::close() // ASSERT(currentThread() == m_openingThread); sqlite3* db = m_db; { - MutexLocker locker(m_databaseClosingMutex); + LockHolder locker(m_databaseClosingMutex); m_db = 0; } sqlite3_close(db); @@ -158,27 +158,7 @@ void SQLiteDatabase::overrideUnauthorizedFunctions() sqlite3_create_function(m_db, functionParameter.first, functionParameter.second, SQLITE_UTF8, const_cast<char*>(functionParameter.first), unauthorizedSQLFunction, 0, 0); } -void SQLiteDatabase::interrupt() -{ - m_interrupted = true; - while (!m_lockingMutex.tryLock()) { - MutexLocker locker(m_databaseClosingMutex); - if (!m_db) - return; - sqlite3_interrupt(m_db); - std::this_thread::yield(); - } - - m_lockingMutex.unlock(); -} - -bool SQLiteDatabase::isInterrupted() -{ - ASSERT(!m_lockingMutex.tryLock()); - return m_interrupted; -} - -void SQLiteDatabase::setFullsync(bool fsync) +void SQLiteDatabase::setFullsync(bool fsync) { if (fsync) executeCommand(ASCIILiteral("PRAGMA fullfsync = 1;")); @@ -191,7 +171,7 @@ int64_t SQLiteDatabase::maximumSize() int64_t maxPageCount = 0; { - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); SQLiteStatement statement(*this, ASCIILiteral("PRAGMA max_page_count")); maxPageCount = statement.getColumnInt64(0); @@ -211,12 +191,12 @@ void SQLiteDatabase::setMaximumSize(int64_t size) ASSERT(currentPageSize || !m_db); int64_t newMaxPageCount = currentPageSize ? size / currentPageSize : 0; - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); SQLiteStatement statement(*this, "PRAGMA max_page_count = " + String::number(newMaxPageCount)); statement.prepare(); - if (statement.step() != SQLResultRow) + if (statement.step() != SQLITE_ROW) LOG_ERROR("Failed to set maximum size of database to %lli bytes", static_cast<long long>(size)); enableAuthorizer(true); @@ -228,7 +208,7 @@ int SQLiteDatabase::pageSize() // Since the page size of a database is locked in at creation and therefore cannot be dynamic, // we can cache the value for future use if (m_pageSize == -1) { - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); SQLiteStatement statement(*this, ASCIILiteral("PRAGMA page_size")); @@ -245,7 +225,7 @@ int64_t SQLiteDatabase::freeSpaceSize() int64_t freelistCount = 0; { - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); // Note: freelist_count was added in SQLite 3.4.1. SQLiteStatement statement(*this, ASCIILiteral("PRAGMA freelist_count")); @@ -261,7 +241,7 @@ int64_t SQLiteDatabase::totalSize() int64_t pageCount = 0; { - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); SQLiteStatement statement(*this, ASCIILiteral("PRAGMA page_count")); pageCount = statement.getColumnInt64(0); @@ -340,7 +320,7 @@ int SQLiteDatabase::runVacuumCommand() int SQLiteDatabase::runIncrementalVacuumCommand() { - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); enableAuthorizer(false); if (!executeCommand(ASCIILiteral("PRAGMA incremental_vacuum"))) @@ -350,6 +330,13 @@ int SQLiteDatabase::runIncrementalVacuumCommand() return lastError(); } +void SQLiteDatabase::interrupt() +{ + LockHolder locker(m_databaseClosingMutex); + if (m_db) + sqlite3_interrupt(m_db); +} + int64_t SQLiteDatabase::lastInsertRowID() { if (!m_db) @@ -388,12 +375,8 @@ const char* SQLiteDatabase::lastErrorMsg() #ifndef NDEBUG void SQLiteDatabase::disableThreadingChecks() { - // This doesn't guarantee that SQList was compiled with -DTHREADSAFE, or that you haven't turned off the mutexes. -#if SQLITE_VERSION_NUMBER >= 3003001 + // Note that SQLite could be compiled with -DTHREADSAFE, or you may have turned off the mutexes. m_sharable = true; -#else - ASSERT(0); // Your SQLite doesn't support sharing handles across threads. -#endif } #endif @@ -457,7 +440,6 @@ int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const cha return auth->allowAlterTable(parameter1, parameter2); case SQLITE_REINDEX: return auth->allowReindex(parameter1); -#if SQLITE_VERSION_NUMBER >= 3003013 case SQLITE_ANALYZE: return auth->allowAnalyze(parameter1); case SQLITE_CREATE_VTABLE: @@ -466,14 +448,13 @@ int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const cha return auth->dropVTable(parameter1, parameter2); case SQLITE_FUNCTION: return auth->allowFunction(parameter2); -#endif default: ASSERT_NOT_REACHED(); return SQLAuthDeny; } } -void SQLiteDatabase::setAuthorizer(PassRefPtr<DatabaseAuthorizer> auth) +void SQLiteDatabase::setAuthorizer(DatabaseAuthorizer& authorizer) { if (!m_db) { LOG_ERROR("Attempt to set an authorizer on a non-open SQL database"); @@ -481,9 +462,9 @@ void SQLiteDatabase::setAuthorizer(PassRefPtr<DatabaseAuthorizer> auth) return; } - MutexLocker locker(m_authorizerLock); + LockHolder locker(m_authorizerLock); - m_authorizer = auth; + m_authorizer = &authorizer; enableAuthorizer(true); } diff --git a/Source/WebCore/platform/sql/SQLiteDatabase.h b/Source/WebCore/platform/sql/SQLiteDatabase.h index a8d8c7a8e..ee9ba2be1 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabase.h +++ b/Source/WebCore/platform/sql/SQLiteDatabase.h @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,10 +24,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLiteDatabase_h -#define SQLiteDatabase_h +#pragma once #include <functional> +#include <sqlite3.h> +#include <wtf/Lock.h> #include <wtf/Threading.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -44,40 +45,32 @@ class DatabaseAuthorizer; class SQLiteStatement; class SQLiteTransaction; -extern const int SQLResultDone; -extern const int SQLResultError; -extern const int SQLResultOk; -extern const int SQLResultRow; -extern const int SQLResultSchema; -extern const int SQLResultFull; -extern const int SQLResultInterrupt; -extern const int SQLResultConstraint; - class SQLiteDatabase { WTF_MAKE_NONCOPYABLE(SQLiteDatabase); friend class SQLiteTransaction; public: - SQLiteDatabase(); - ~SQLiteDatabase(); + WEBCORE_EXPORT SQLiteDatabase(); + WEBCORE_EXPORT ~SQLiteDatabase(); - bool open(const String& filename, bool forWebSQLDatabase = false); + WEBCORE_EXPORT bool open(const String& filename, bool forWebSQLDatabase = false); bool isOpen() const { return m_db; } - void close(); - void interrupt(); - bool isInterrupted(); + WEBCORE_EXPORT void close(); void updateLastChangesCount(); - bool executeCommand(const String&); + WEBCORE_EXPORT bool executeCommand(const String&); bool returnsAtLeastOneResult(const String&); - bool tableExists(const String&); + WEBCORE_EXPORT bool tableExists(const String&); void clearAllTables(); int runVacuumCommand(); int runIncrementalVacuumCommand(); bool transactionInProgress() const { return m_transactionInProgress; } - + + // Aborts the current database operation. This is thread safe. + void interrupt(); + int64_t lastInsertRowID(); int lastChanges(); @@ -104,19 +97,20 @@ public: enum SynchronousPragma { SyncOff = 0, SyncNormal = 1, SyncFull = 2 }; void setSynchronous(SynchronousPragma); - int lastError(); - const char* lastErrorMsg(); + WEBCORE_EXPORT int lastError(); + WEBCORE_EXPORT const char* lastErrorMsg(); - sqlite3* sqlite3Handle() const { + sqlite3* sqlite3Handle() const + { #if !PLATFORM(IOS) ASSERT(m_sharable || currentThread() == m_openingThread || !m_db); #endif return m_db; } - void setAuthorizer(PassRefPtr<DatabaseAuthorizer>); + void setAuthorizer(DatabaseAuthorizer&); - Mutex& databaseMutex() { return m_lockingMutex; } + Lock& databaseMutex() { return m_lockingMutex; } bool isAutoCommitOn() const; // The SQLite AUTO_VACUUM pragma can be either NONE, FULL, or INCREMENTAL. @@ -131,15 +125,15 @@ public: enum AutoVacuumPragma { AutoVacuumNone = 0, AutoVacuumFull = 1, AutoVacuumIncremental = 2 }; bool turnOnIncrementalAutoVacuum(); - void setCollationFunction(const String& collationName, std::function<int(int, const void*, int, const void*)>); + WEBCORE_EXPORT void setCollationFunction(const String& collationName, std::function<int(int, const void*, int, const void*)>); void removeCollationFunction(const String& collationName); // Set this flag to allow access from multiple threads. Not all multi-threaded accesses are safe! // See http://www.sqlite.org/cvstrac/wiki?p=MultiThreading for more info. #ifndef NDEBUG - void disableThreadingChecks(); + WEBCORE_EXPORT void disableThreadingChecks(); #else - void disableThreadingChecks() {} + WEBCORE_EXPORT void disableThreadingChecks() {} #endif private: @@ -151,27 +145,24 @@ private: void overrideUnauthorizedFunctions(); - sqlite3* m_db; - int m_pageSize; + sqlite3* m_db { nullptr }; + int m_pageSize { -1 }; - bool m_transactionInProgress; - bool m_sharable; + bool m_transactionInProgress { false }; + bool m_sharable { false }; - Mutex m_authorizerLock; + Lock m_authorizerLock; RefPtr<DatabaseAuthorizer> m_authorizer; - Mutex m_lockingMutex; - ThreadIdentifier m_openingThread; + Lock m_lockingMutex; + ThreadIdentifier m_openingThread { 0 }; - Mutex m_databaseClosingMutex; - bool m_interrupted; + Lock m_databaseClosingMutex; - int m_openError; + int m_openError { SQLITE_ERROR }; CString m_openErrorMessage; - int m_lastChangesCount; + int m_lastChangesCount { 0 }; }; } // namespace WebCore - -#endif diff --git a/Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp b/Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp index 8438ac18b..3754a4c48 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp +++ b/Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp @@ -27,7 +27,7 @@ #include "SQLiteDatabaseTracker.h" #include <mutex> -#include <wtf/NeverDestroyed.h> +#include <wtf/Lock.h> namespace WebCore { @@ -36,11 +36,7 @@ namespace SQLiteDatabaseTracker { static SQLiteDatabaseTrackerClient* s_staticSQLiteDatabaseTrackerClient = nullptr; static unsigned s_transactionInProgressCounter = 0; -static std::mutex& transactionInProgressMutex() -{ - static NeverDestroyed<std::mutex> tipMutex; - return tipMutex; -} +static StaticLock transactionInProgressMutex; void setClient(SQLiteDatabaseTrackerClient* client) { @@ -54,7 +50,7 @@ void incrementTransactionInProgressCount() if (!s_staticSQLiteDatabaseTrackerClient) return; - std::lock_guard<std::mutex> lock(transactionInProgressMutex()); + std::lock_guard<StaticLock> lock(transactionInProgressMutex); s_transactionInProgressCounter++; if (s_transactionInProgressCounter == 1) @@ -66,7 +62,7 @@ void decrementTransactionInProgressCount() if (!s_staticSQLiteDatabaseTrackerClient) return; - std::lock_guard<std::mutex> lock(transactionInProgressMutex()); + std::lock_guard<StaticLock> lock(transactionInProgressMutex); ASSERT(s_transactionInProgressCounter); s_transactionInProgressCounter--; diff --git a/Source/WebCore/platform/sql/SQLiteDatabaseTracker.h b/Source/WebCore/platform/sql/SQLiteDatabaseTracker.h index 483d9afe3..45b01c673 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabaseTracker.h +++ b/Source/WebCore/platform/sql/SQLiteDatabaseTracker.h @@ -32,13 +32,13 @@ namespace WebCore { namespace SQLiteDatabaseTracker { -void decrementTransactionInProgressCount(); -void incrementTransactionInProgressCount(); +WEBCORE_EXPORT void decrementTransactionInProgressCount(); +WEBCORE_EXPORT void incrementTransactionInProgressCount(); -void setClient(SQLiteDatabaseTrackerClient*); +WEBCORE_EXPORT void setClient(SQLiteDatabaseTrackerClient*); #if !ASSERT_DISABLED -bool hasTransactionInProgress(); +WEBCORE_EXPORT bool hasTransactionInProgress(); #endif }; diff --git a/Source/WebCore/platform/sql/SQLiteFileSystem.cpp b/Source/WebCore/platform/sql/SQLiteFileSystem.cpp index e8cfb0e16..d4c968cce 100644 --- a/Source/WebCore/platform/sql/SQLiteFileSystem.cpp +++ b/Source/WebCore/platform/sql/SQLiteFileSystem.cpp @@ -28,14 +28,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define __STDC_FORMAT_MACROS #include "config.h" #include "SQLiteFileSystem.h" #include "FileSystem.h" #include "SQLiteDatabase.h" #include "SQLiteStatement.h" -#include <inttypes.h> #include <sqlite3.h> #if PLATFORM(IOS) @@ -50,33 +48,7 @@ SQLiteFileSystem::SQLiteFileSystem() int SQLiteFileSystem::openDatabase(const String& filename, sqlite3** database, bool) { - return sqlite3_open(filename.utf8().data(), database); -} - -String SQLiteFileSystem::getFileNameForNewDatabase(const String& dbDir, const String&, - const String&, SQLiteDatabase* db) -{ - // try to get the next sequence number from the given database - // if we can't get a number, return an empty string - SQLiteStatement sequenceStatement(*db, "SELECT seq FROM sqlite_sequence WHERE name='Databases';"); - if (sequenceStatement.prepare() != SQLResultOk) - return String(); - int result = sequenceStatement.step(); - int64_t seq = 0; - if (result == SQLResultRow) - seq = sequenceStatement.getColumnInt64(0); - else if (result != SQLResultDone) - return String(); - sequenceStatement.finalize(); - - // increment the number until we can use it to form a file name that doesn't exist - String fileName; - do { - ++seq; - fileName = pathByAppendingComponent(dbDir, String::format("%016" PRIx64 ".db", seq)); - } while (fileExists(fileName)); - - return String::format("%016" PRIx64 ".db", seq); + return sqlite3_open_v2(fileSystemRepresentation(filename).data(), database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_AUTOPROXY, nullptr); } String SQLiteFileSystem::appendDatabaseFileNameToPath(const String& path, const String& fileName) @@ -111,7 +83,16 @@ bool SQLiteFileSystem::deleteEmptyDatabaseDirectory(const String& path) bool SQLiteFileSystem::deleteDatabaseFile(const String& fileName) { - return deleteFile(fileName); + String walFileName = makeString(fileName, ASCIILiteral("-wal")); + String shmFileName = makeString(fileName, ASCIILiteral("-shm")); + + // Try to delete all three files whether or not they are there. + deleteFile(fileName); + deleteFile(walFileName); + deleteFile(shmFileName); + + // If any of the wal or shm files remain after the delete attempt, the overall delete operation failed. + return !fileExists(fileName) && !fileExists(walFileName) && !fileExists(shmFileName); } #if PLATFORM(IOS) diff --git a/Source/WebCore/platform/sql/SQLiteFileSystem.h b/Source/WebCore/platform/sql/SQLiteFileSystem.h index 9c5f29512..18d942aa1 100644 --- a/Source/WebCore/platform/sql/SQLiteFileSystem.h +++ b/Source/WebCore/platform/sql/SQLiteFileSystem.h @@ -54,15 +54,6 @@ public: // using a custom VFS. static int openDatabase(const String& filename, sqlite3** database, bool forWebSQLDatabase); - // Returns the file name for a database. - // - // dbDir - The directory where all databases are stored. - // dbName - The name of the database. - // originIdentifier - The origin that wants to use this database. - // db - A database with a number generator used to create unique file names. - static String getFileNameForNewDatabase(const String& dbDir, const String& dbName, - const String& originIdentifier, SQLiteDatabase* db); - // Creates an absolute file path given a directory and a file name. // // path - The directory. @@ -97,7 +88,7 @@ public: // Deletes a database file. // // fileName - The file name. - static bool deleteDatabaseFile(const String& fileName); + WEBCORE_EXPORT static bool deleteDatabaseFile(const String& fileName); #if PLATFORM(IOS) // Truncates a database file. Used when MobileSafariSettings deletes a database file, diff --git a/Source/WebCore/platform/sql/SQLiteStatement.cpp b/Source/WebCore/platform/sql/SQLiteStatement.cpp index f254546b6..c8f30ba5d 100644 --- a/Source/WebCore/platform/sql/SQLiteStatement.cpp +++ b/Source/WebCore/platform/sql/SQLiteStatement.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -30,7 +30,8 @@ #include "SQLValue.h" #include <sqlite3.h> #include <wtf/Assertions.h> -#include <wtf/text/StringImpl.h> +#include <wtf/Variant.h> +#include <wtf/text/StringView.h> // SQLite 3.6.16 makes sqlite3_prepare_v2 automatically retry preparing the statement // once if the database scheme has changed. We rely on this behavior. @@ -59,9 +60,7 @@ int SQLiteStatement::prepare() { ASSERT(!m_isPrepared); - MutexLocker databaseLock(m_database.databaseMutex()); - if (m_database.isInterrupted()) - return SQLITE_INTERRUPT; + LockHolder databaseLock(m_database.databaseMutex()); CString query = m_query.stripWhiteSpace().utf8(); @@ -88,10 +87,7 @@ int SQLiteStatement::prepare() int SQLiteStatement::step() { - MutexLocker databaseLock(m_database.databaseMutex()); - if (m_database.isInterrupted()) - return SQLITE_INTERRUPT; - //ASSERT(m_isPrepared); + LockHolder databaseLock(m_database.databaseMutex()); if (!m_statement) return SQLITE_OK; @@ -177,12 +173,13 @@ int SQLiteStatement::bindBlob(int index, const String& text) { // String::characters() returns 0 for the empty string, which SQLite // treats as a null, so we supply a non-null pointer for that case. + auto upconvertedCharacters = StringView(text).upconvertedCharacters(); UChar anyCharacter = 0; const UChar* characters; if (text.isEmpty() && !text.isNull()) characters = &anyCharacter; else - characters = text.deprecatedCharacters(); + characters = upconvertedCharacters; return bindBlob(index, characters, text.length() * sizeof(UChar)); } @@ -195,12 +192,13 @@ int SQLiteStatement::bindText(int index, const String& text) // String::characters() returns 0 for the empty string, which SQLite // treats as a null, so we supply a non-null pointer for that case. + auto upconvertedCharacters = StringView(text).upconvertedCharacters(); UChar anyCharacter = 0; const UChar* characters; if (text.isEmpty() && !text.isNull()) characters = &anyCharacter; else - characters = text.deprecatedCharacters(); + characters = upconvertedCharacters; return sqlite3_bind_text16(m_statement, index, characters, sizeof(UChar) * text.length(), SQLITE_TRANSIENT); } @@ -243,17 +241,11 @@ int SQLiteStatement::bindNull(int index) int SQLiteStatement::bindValue(int index, const SQLValue& value) { - switch (value.type()) { - case SQLValue::StringValue: - return bindText(index, value.string()); - case SQLValue::NumberValue: - return bindDouble(index, value.number()); - case SQLValue::NullValue: - return bindNull(index); - } - - ASSERT_NOT_REACHED(); - return SQLITE_ERROR; + return WTF::switchOn(value, + [&] (const std::nullptr_t&) { return bindNull(index); }, + [&] (const String& string) { return bindText(index, string); }, + [&] (double number) { return bindDouble(index, number); } + ); } unsigned SQLiteStatement::bindParameterCount() const @@ -291,8 +283,7 @@ bool SQLiteStatement::isColumnDeclaredAsBlob(int col) if (prepare() != SQLITE_OK) return false; } - - return equalIgnoringCase(String("BLOB"), String(reinterpret_cast<const UChar*>(sqlite3_column_decltype16(m_statement, col)))); + return equalLettersIgnoringASCIICase(StringView(sqlite3_column_decltype(m_statement, col)), "blob"); } String SQLiteStatement::getColumnName(int col) @@ -311,9 +302,9 @@ SQLValue SQLiteStatement::getColumnValue(int col) ASSERT(col >= 0); if (!m_statement) if (prepareAndStep() != SQLITE_ROW) - return SQLValue(); + return nullptr; if (columnCount() <= col) - return SQLValue(); + return nullptr; // SQLite is typed per value. optional column types are // "(mostly) ignored" @@ -321,19 +312,20 @@ SQLValue SQLiteStatement::getColumnValue(int col) switch (sqlite3_value_type(value)) { case SQLITE_INTEGER: // SQLValue and JS don't represent integers, so use FLOAT -case case SQLITE_FLOAT: - return SQLValue(sqlite3_value_double(value)); + return sqlite3_value_double(value); case SQLITE_BLOB: // SQLValue and JS don't represent blobs, so use TEXT -case case SQLITE_TEXT: { const UChar* string = reinterpret_cast<const UChar*>(sqlite3_value_text16(value)); - return SQLValue(StringImpl::create8BitIfPossible(string)); + return StringImpl::create8BitIfPossible(string); } case SQLITE_NULL: - return SQLValue(); + return nullptr; default: break; } + ASSERT_NOT_REACHED(); - return SQLValue(); + return nullptr; } String SQLiteStatement::getColumnText(int col) @@ -428,32 +420,30 @@ void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result) result[i] = (static_cast<const unsigned char*>(blob))[i]; } -const void* SQLiteStatement::getColumnBlob(int col, int& size) +void SQLiteStatement::getColumnBlobAsVector(int col, Vector<uint8_t>& result) { ASSERT(col >= 0); - size = 0; - - if (finalize() != SQLITE_OK) - LOG(SQLDatabase, "Finalize failed"); - if (prepare() != SQLITE_OK) { - LOG(SQLDatabase, "Prepare failed"); - return 0; + if (!m_statement && prepareAndStep() != SQLITE_ROW) { + result.clear(); + return; } - if (step() != SQLITE_ROW) { - LOG(SQLDatabase, "Step wasn't a row"); - return 0; + + if (columnCount() <= col) { + result.clear(); + return; } - if (columnCount() <= col) - return 0; - const void* blob = sqlite3_column_blob(m_statement, col); - if (!blob) - return 0; - - size = sqlite3_column_bytes(m_statement, col); - return blob; + if (!blob) { + result.clear(); + return; + } + + int size = sqlite3_column_bytes(m_statement, col); + result.resize((size_t)size); + for (int i = 0; i < size; ++i) + result[i] = (static_cast<const uint8_t*>(blob))[i]; } bool SQLiteStatement::returnTextResults(int col, Vector<String>& v) @@ -486,7 +476,7 @@ bool SQLiteStatement::returnIntResults(int col, Vector<int>& v) finalize(); if (prepare() != SQLITE_OK) return false; - + while (step() == SQLITE_ROW) v.append(getColumnInt(col)); bool result = true; @@ -506,7 +496,7 @@ bool SQLiteStatement::returnInt64Results(int col, Vector<int64_t>& v) finalize(); if (prepare() != SQLITE_OK) return false; - + while (step() == SQLITE_ROW) v.append(getColumnInt64(col)); bool result = true; @@ -540,7 +530,7 @@ bool SQLiteStatement::returnDoubleResults(int col, Vector<double>& v) bool SQLiteStatement::isExpired() { - return !m_statement || sqlite3_expired(m_statement); + return !m_statement; } } // namespace WebCore diff --git a/Source/WebCore/platform/sql/SQLiteStatement.h b/Source/WebCore/platform/sql/SQLiteStatement.h index 8a9e4ac3e..a193d8c24 100644 --- a/Source/WebCore/platform/sql/SQLiteStatement.h +++ b/Source/WebCore/platform/sql/SQLiteStatement.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,44 +23,42 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLiteStatement_h -#define SQLiteStatement_h +#pragma once +#include "SQLValue.h" #include "SQLiteDatabase.h" struct sqlite3_stmt; namespace WebCore { -class SQLValue; - class SQLiteStatement { WTF_MAKE_NONCOPYABLE(SQLiteStatement); WTF_MAKE_FAST_ALLOCATED; public: - SQLiteStatement(SQLiteDatabase&, const String&); - ~SQLiteStatement(); + WEBCORE_EXPORT SQLiteStatement(SQLiteDatabase&, const String&); + WEBCORE_EXPORT ~SQLiteStatement(); - int prepare(); - int bindBlob(int index, const void* blob, int size); - int bindBlob(int index, const String&); - int bindText(int index, const String&); - int bindInt(int index, int); - int bindInt64(int index, int64_t); - int bindDouble(int index, double); - int bindNull(int index); - int bindValue(int index, const SQLValue&); - unsigned bindParameterCount() const; + WEBCORE_EXPORT int prepare(); + WEBCORE_EXPORT int bindBlob(int index, const void* blob, int size); + WEBCORE_EXPORT int bindBlob(int index, const String&); + WEBCORE_EXPORT int bindText(int index, const String&); + WEBCORE_EXPORT int bindInt(int index, int); + WEBCORE_EXPORT int bindInt64(int index, int64_t); + WEBCORE_EXPORT int bindDouble(int index, double); + WEBCORE_EXPORT int bindNull(int index); + WEBCORE_EXPORT int bindValue(int index, const SQLValue&); + WEBCORE_EXPORT unsigned bindParameterCount() const; - int step(); - int finalize(); - int reset(); + WEBCORE_EXPORT int step(); + WEBCORE_EXPORT int finalize(); + WEBCORE_EXPORT int reset(); int prepareAndStep() { if (int error = prepare()) return error; return step(); } // prepares, steps, and finalizes the query. // returns true if all 3 steps succeed with step() returning SQLITE_DONE // returns false otherwise - bool executeCommand(); + WEBCORE_EXPORT bool executeCommand(); // prepares, steps, and finalizes. // returns true is step() returns SQLITE_ROW @@ -73,24 +71,24 @@ public: // returned in the last step() int columnCount(); - bool isColumnNull(int col); - bool isColumnDeclaredAsBlob(int col); + WEBCORE_EXPORT bool isColumnNull(int col); + WEBCORE_EXPORT bool isColumnDeclaredAsBlob(int col); String getColumnName(int col); SQLValue getColumnValue(int col); - String getColumnText(int col); + WEBCORE_EXPORT String getColumnText(int col); double getColumnDouble(int col); - int getColumnInt(int col); - int64_t getColumnInt64(int col); - const void* getColumnBlob(int col, int& size); - String getColumnBlobAsString(int col); - void getColumnBlobAsVector(int col, Vector<char>&); + WEBCORE_EXPORT int getColumnInt(int col); + WEBCORE_EXPORT int64_t getColumnInt64(int col); + WEBCORE_EXPORT String getColumnBlobAsString(int col); + WEBCORE_EXPORT void getColumnBlobAsVector(int col, Vector<char>&); + WEBCORE_EXPORT void getColumnBlobAsVector(int col, Vector<uint8_t>&); bool returnTextResults(int col, Vector<String>&); bool returnIntResults(int col, Vector<int>&); bool returnInt64Results(int col, Vector<int64_t>&); bool returnDoubleResults(int col, Vector<double>&); - SQLiteDatabase* database() { return &m_database; } + SQLiteDatabase& database() { return m_database; } const String& query() const { return m_query; } @@ -104,5 +102,3 @@ private: }; } // namespace WebCore - -#endif // SQLiteStatement_h diff --git a/Source/WebCore/platform/sql/SQLiteTransaction.cpp b/Source/WebCore/platform/sql/SQLiteTransaction.cpp index d15ced3ae..54e0a1802 100644 --- a/Source/WebCore/platform/sql/SQLiteTransaction.cpp +++ b/Source/WebCore/platform/sql/SQLiteTransaction.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/platform/sql/SQLiteTransaction.h b/Source/WebCore/platform/sql/SQLiteTransaction.h index 0546f4f24..b9d1f7940 100644 --- a/Source/WebCore/platform/sql/SQLiteTransaction.h +++ b/Source/WebCore/platform/sql/SQLiteTransaction.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -36,16 +36,19 @@ class SQLiteDatabase; class SQLiteTransaction { WTF_MAKE_NONCOPYABLE(SQLiteTransaction); WTF_MAKE_FAST_ALLOCATED; public: - SQLiteTransaction(SQLiteDatabase& db, bool readOnly = false); - ~SQLiteTransaction(); + WEBCORE_EXPORT SQLiteTransaction(SQLiteDatabase& db, bool readOnly = false); + WEBCORE_EXPORT ~SQLiteTransaction(); - void begin(); - void commit(); - void rollback(); + WEBCORE_EXPORT void begin(); + WEBCORE_EXPORT void commit(); + WEBCORE_EXPORT void rollback(); void stop(); bool inProgress() const { return m_inProgress; } bool wasRolledBackBySqlite() const; + + SQLiteDatabase& database() const { return m_db; } + private: SQLiteDatabase& m_db; bool m_inProgress; |