diff options
author | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
---|---|---|
committer | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
commit | d8543bb6618c17b12da906afa77d216f58cf4058 (patch) | |
tree | c58dc05ed86825bd0ef8d305d58c8205106b540f /WebCore/platform/sql | |
download | external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2 |
external/webkit r30707
Diffstat (limited to 'WebCore/platform/sql')
-rw-r--r-- | WebCore/platform/sql/SQLValue.cpp | 56 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLValue.h | 58 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteAuthorizer.cpp | 39 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteAuthorizer.h | 88 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteDatabase.cpp | 353 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteDatabase.h | 130 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteStatement.cpp | 453 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteStatement.h | 100 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteTransaction.cpp | 80 | ||||
-rw-r--r-- | WebCore/platform/sql/SQLiteTransaction.h | 56 |
10 files changed, 1413 insertions, 0 deletions
diff --git a/WebCore/platform/sql/SQLValue.cpp b/WebCore/platform/sql/SQLValue.cpp new file mode 100644 index 0000000..7e178f9 --- /dev/null +++ b/WebCore/platform/sql/SQLValue.cpp @@ -0,0 +1,56 @@ +/* + * 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_number = val.m_number; + m_string = val.m_string.copy(); + m_type = val.m_type; +} + +String SQLValue::string() const +{ + ASSERT(m_type == StringValue); + + // Must return a copy since ref-shared Strings are not thread safe + return m_string.copy(); +} + +double SQLValue::number() const +{ + ASSERT(m_type == NumberValue); + + return m_number; +} + +} diff --git a/WebCore/platform/sql/SQLValue.h b/WebCore/platform/sql/SQLValue.h new file mode 100644 index 0000000..7d85051 --- /dev/null +++ b/WebCore/platform/sql/SQLValue.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef SQLValue_h +#define SQLValue_h + +#include "PlatformString.h" +#include <wtf/Threading.h> + +namespace WebCore { + + class SQLValue { + public: + enum Type { NullValue, NumberValue, StringValue }; + + SQLValue() : m_type(NullValue) { } + SQLValue(double number) : m_type(NumberValue), m_number(number) { } + SQLValue(const String& s) : m_type(StringValue), 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/WebCore/platform/sql/SQLiteAuthorizer.cpp b/WebCore/platform/sql/SQLiteAuthorizer.cpp new file mode 100644 index 0000000..e1014ec --- /dev/null +++ b/WebCore/platform/sql/SQLiteAuthorizer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "SQLiteAuthorizer.h" + +#include <sqlite3.h> + +namespace WebCore { + +const int SQLAuthAllow = SQLITE_OK; +const int SQLAuthIgnore = SQLITE_IGNORE; +const int SQLAuthDeny = SQLITE_DENY; + +} // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteAuthorizer.h b/WebCore/platform/sql/SQLiteAuthorizer.h new file mode 100644 index 0000000..0bb0fb3 --- /dev/null +++ b/WebCore/platform/sql/SQLiteAuthorizer.h @@ -0,0 +1,88 @@ +/* + * 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. + */ +#ifndef SQLiteAuthorizer_h +#define SQLiteAuthorizer_h + +#include <wtf/Threading.h> + +namespace WebCore { + +class String; + +extern const int SQLAuthAllow; +extern const int SQLAuthIgnore; +extern const int SQLAuthDeny; + +class SQLiteAuthorizer : public ThreadSafeShared<SQLiteAuthorizer> { +public: + virtual ~SQLiteAuthorizer() { } + + virtual int createTable(const String& tableName) { return SQLAuthAllow; } + virtual int createTempTable(const String& tableName) { return SQLAuthAllow; } + virtual int dropTable(const String& tableName) { return SQLAuthAllow; } + virtual int dropTempTable(const String& tableName) { return SQLAuthAllow; } + virtual int allowAlterTable(const String& databaseName, const String& tableName) { return SQLAuthAllow; } + + virtual int createIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; } + virtual int createTempIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; } + virtual int dropIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; } + virtual int dropTempIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; } + + virtual int createTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; } + virtual int createTempTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; } + virtual int dropTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; } + virtual int dropTempTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; } + + virtual int createView(const String& viewName) { return SQLAuthAllow; } + virtual int createTempView(const String& viewName) { return SQLAuthAllow; } + virtual int dropView(const String& viewName) { return SQLAuthAllow; } + virtual int dropTempView(const String& viewName) { return SQLAuthAllow; } + + virtual int createVTable(const String& tableName, const String& moduleName) { return SQLAuthAllow; } + virtual int dropVTable(const String& tableName, const String& moduleName) { return SQLAuthAllow; } + + virtual int allowDelete(const String& tableName) { return SQLAuthAllow; } + virtual int allowInsert(const String& tableName) { return SQLAuthAllow; } + virtual int allowUpdate(const String& tableName, const String& columnName) { return SQLAuthAllow; } + virtual int allowTransaction() { return SQLAuthAllow; } + + virtual int allowSelect() { return SQLAuthAllow; } + virtual int allowRead(const String& tableName, const String& columnName) { return SQLAuthAllow; } + + virtual int allowAttach(const String& filename) { return SQLAuthAllow; } + virtual int allowDetach(const String& databaseName) { return SQLAuthAllow; } + + virtual int allowReindex(const String& indexName) { return SQLAuthAllow; } + virtual int allowAnalyze(const String& tableName) { return SQLAuthAllow; } + virtual int allowFunction(const String& functionName) { return SQLAuthAllow; } + virtual int allowPragma(const String& pragmaName, const String& firstArgument) { return SQLAuthAllow; } +}; + +} // namespace WebCore + +#endif // SQLiteAuthorizer_h diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp new file mode 100644 index 0000000..7768f66 --- /dev/null +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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 "SQLiteDatabase.h" + +#include "Logging.h" +#include "SQLiteAuthorizer.h" +#include "SQLiteStatement.h" + +#include <sqlite3.h> + +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; + + +SQLiteDatabase::SQLiteDatabase() + : m_db(0) + , m_pageSize(-1) + , m_transactionInProgress(false) + , m_openingThread(0) +{ +} + +SQLiteDatabase::~SQLiteDatabase() +{ + close(); +} + +bool SQLiteDatabase::open(const String& filename) +{ + close(); + + // SQLite expects a null terminator on its UTF-16 strings. + String path = filename; + m_lastError = sqlite3_open16(path.charactersWithNullTermination(), &m_db); + if (m_lastError != SQLITE_OK) { + LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(), + sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + m_db = 0; + return false; + } + + if (isOpen()) + m_openingThread = currentThread(); + + if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand()) + LOG_ERROR("SQLite database could not set temp_store to memory"); + + return isOpen(); +} + +void SQLiteDatabase::close() +{ + if (m_db) { + // FIXME: This is being called on themain thread during JS GC. <rdar://problem/5739818> + // ASSERT(currentThread() == m_openingThread); + sqlite3_close(m_db); + m_db = 0; + } + + m_openingThread = 0; +} + +void SQLiteDatabase::setFullsync(bool fsync) +{ + if (fsync) + executeCommand("PRAGMA fullfsync = 1;"); + else + executeCommand("PRAGMA fullfsync = 0;"); +} + +int64_t SQLiteDatabase::maximumSize() +{ + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + + SQLiteStatement statement(*this, "PRAGMA max_page_count"); + int64_t size = statement.getColumnInt64(0) * pageSize(); + + enableAuthorizer(true); + return size; +} + +void SQLiteDatabase::setMaximumSize(int64_t size) +{ + if (size < 0) + size = 0; + + int currentPageSize = pageSize(); + + ASSERT(currentPageSize); + int64_t newMaxPageCount = currentPageSize ? size / currentPageSize : 0; + + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + + SQLiteStatement statement(*this, "PRAGMA max_page_count = " + String::number(newMaxPageCount)); + statement.prepare(); + if (statement.step() != SQLResultRow) + LOG_ERROR("Failed to set maximum size of database to %lli bytes", size); + + enableAuthorizer(true); + +} + +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); + enableAuthorizer(false); + + SQLiteStatement statement(*this, "PRAGMA page_size"); + m_pageSize = statement.getColumnInt(0); + + enableAuthorizer(true); + } + + return m_pageSize; +} + +void SQLiteDatabase::setSynchronous(SynchronousPragma sync) +{ + executeCommand(String::format("PRAGMA synchronous = %i", sync)); +} + +void SQLiteDatabase::setBusyTimeout(int ms) +{ + if (m_db) + sqlite3_busy_timeout(m_db, ms); + else + LOG(SQLDatabase, "BusyTimeout set on non-open database"); +} + +void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int)) +{ + if (m_db) + sqlite3_busy_handler(m_db, handler, NULL); + else + LOG(SQLDatabase, "Busy handler set on non-open database"); +} + +bool SQLiteDatabase::executeCommand(const String& sql) +{ + return SQLiteStatement(*this, sql).executeCommand(); +} + +bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql) +{ + return SQLiteStatement(*this, sql).returnsAtLeastOneResult(); +} + +bool SQLiteDatabase::tableExists(const String& tablename) +{ + if (!isOpen()) + return false; + + String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';"; + + SQLiteStatement sql(*this, statement); + sql.prepare(); + return sql.step() == SQLITE_ROW; +} + +void SQLiteDatabase::clearAllTables() +{ + String query = "SELECT name FROM sqlite_master WHERE type='table';"; + Vector<String> tables; + if (!SQLiteStatement(*this, query).returnTextResults(0, tables)) { + LOG(SQLDatabase, "Unable to retrieve list of tables from database"); + return; + } + + for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) { + if (*table == "sqlite_sequence") + continue; + if (!executeCommand("DROP TABLE " + *table)) + LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data()); + } +} + +void SQLiteDatabase::runVacuumCommand() +{ + if (!executeCommand("VACUUM;")) + LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg()); +} + +int64_t SQLiteDatabase::lastInsertRowID() +{ + if (!m_db) + return 0; + return sqlite3_last_insert_rowid(m_db); +} + +int SQLiteDatabase::lastChanges() +{ + if (!m_db) + return 0; + return sqlite3_changes(m_db); +} + +int SQLiteDatabase::lastError() +{ + return m_db ? sqlite3_errcode(m_db) : SQLITE_ERROR; +} + +const char* SQLiteDatabase::lastErrorMsg() +{ + return sqlite3_errmsg(m_db); +} + +int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/) +{ + SQLiteAuthorizer* auth = static_cast<SQLiteAuthorizer*>(userData); + ASSERT(auth); + + switch (actionCode) { + case SQLITE_CREATE_INDEX: + return auth->createIndex(parameter1, parameter2); + case SQLITE_CREATE_TABLE: + return auth->createTable(parameter1); + case SQLITE_CREATE_TEMP_INDEX: + return auth->createTempIndex(parameter1, parameter2); + case SQLITE_CREATE_TEMP_TABLE: + return auth->createTempTable(parameter1); + case SQLITE_CREATE_TEMP_TRIGGER: + return auth->createTempTrigger(parameter1, parameter2); + case SQLITE_CREATE_TEMP_VIEW: + return auth->createTempView(parameter1); + case SQLITE_CREATE_TRIGGER: + return auth->createTrigger(parameter1, parameter2); + case SQLITE_CREATE_VIEW: + return auth->createView(parameter1); + case SQLITE_DELETE: + return auth->allowDelete(parameter1); + case SQLITE_DROP_INDEX: + return auth->dropIndex(parameter1, parameter2); + case SQLITE_DROP_TABLE: + return auth->dropTable(parameter1); + case SQLITE_DROP_TEMP_INDEX: + return auth->dropTempIndex(parameter1, parameter2); + case SQLITE_DROP_TEMP_TABLE: + return auth->dropTempTable(parameter1); + case SQLITE_DROP_TEMP_TRIGGER: + return auth->dropTempTrigger(parameter1, parameter2); + case SQLITE_DROP_TEMP_VIEW: + return auth->dropTempView(parameter1); + case SQLITE_DROP_TRIGGER: + return auth->dropTrigger(parameter1, parameter2); + case SQLITE_DROP_VIEW: + return auth->dropView(parameter1); + case SQLITE_INSERT: + return auth->allowInsert(parameter1); + case SQLITE_PRAGMA: + return auth->allowPragma(parameter1, parameter2); + case SQLITE_READ: + return auth->allowRead(parameter1, parameter2); + case SQLITE_SELECT: + return auth->allowSelect(); + case SQLITE_TRANSACTION: + return auth->allowTransaction(); + case SQLITE_UPDATE: + return auth->allowUpdate(parameter1, parameter2); + case SQLITE_ATTACH: + return auth->allowAttach(parameter1); + case SQLITE_DETACH: + return auth->allowDetach(parameter1); + case SQLITE_ALTER_TABLE: + 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: + return auth->createVTable(parameter1, parameter2); + case SQLITE_DROP_VTABLE: + return auth->dropVTable(parameter1, parameter2); + case SQLITE_FUNCTION: + return auth->allowFunction(parameter1); +#endif + default: + ASSERT_NOT_REACHED(); + return SQLAuthDeny; + } +} + +void SQLiteDatabase::setAuthorizer(PassRefPtr<SQLiteAuthorizer> auth) +{ + if (!m_db) { + LOG_ERROR("Attempt to set an authorizer on a non-open SQL database"); + ASSERT_NOT_REACHED(); + return; + } + + MutexLocker locker(m_authorizerLock); + + m_authorizer = auth; + + enableAuthorizer(true); +} + +void SQLiteDatabase::enableAuthorizer(bool enable) +{ + if (m_authorizer && enable) + sqlite3_set_authorizer(m_db, SQLiteDatabase::authorizerFunction, m_authorizer.get()); + else + sqlite3_set_authorizer(m_db, NULL, 0); +} + +void SQLiteDatabase::lock() +{ + m_lockingMutex.lock(); +} + +void SQLiteDatabase::unlock() +{ + m_lockingMutex.unlock(); +} + +} // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h new file mode 100644 index 0000000..20f461d --- /dev/null +++ b/WebCore/platform/sql/SQLiteDatabase.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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. + */ + +#ifndef SQLDatabase_h +#define SQLDatabase_h + +#include "PlatformString.h" +#include <wtf/Threading.h> + +#if COMPILER(MSVC) +#pragma warning(disable: 4800) +#endif + +struct sqlite3; + +namespace WebCore { + +class SQLiteAuthorizer; +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; + +class SQLiteDatabase : public Noncopyable { + friend class SQLiteTransaction; +public: + SQLiteDatabase(); + ~SQLiteDatabase(); + + bool open(const String& filename); + bool isOpen() const { return m_db; } + void close(); + + bool executeCommand(const String&); + bool returnsAtLeastOneResult(const String&); + + bool tableExists(const String&); + void clearAllTables(); + void runVacuumCommand(); + + bool transactionInProgress() const { return m_transactionInProgress; } + + int64_t lastInsertRowID(); + int lastChanges(); + + void setBusyTimeout(int ms); + void setBusyHandler(int(*)(void*, int)); + + void setFullsync(bool); + + // Gets/sets the maximum size in bytes + // Depending on per-database attributes, the size will only be settable in units that are the page size of the database, which is established at creation + // These chunks will never be anything other than 512, 1024, 2048, 4096, 8192, 16384, or 32768 bytes in size. + // setMaximumSize() will round the size down to the next smallest chunk if the passed size doesn't align. + int64_t maximumSize(); + void setMaximumSize(int64_t); + + // The SQLite SYNCHRONOUS pragma can be either FULL, NORMAL, or OFF + // FULL - Any writing calls to the DB block until the data is actually on the disk surface + // NORMAL - SQLite pauses at some critical moments when writing, but much less than FULL + // OFF - Calls return immediately after the data has been passed to disk + enum SynchronousPragma { SyncOff = 0, SyncNormal = 1, SyncFull = 2 }; + void setSynchronous(SynchronousPragma); + + int lastError(); + const char* lastErrorMsg(); + + sqlite3* sqlite3Handle() const { + ASSERT(currentThread() == m_openingThread); + return m_db; + } + + void setAuthorizer(PassRefPtr<SQLiteAuthorizer>); + + // (un)locks the database like a mutex + void lock(); + void unlock(); + +private: + static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*); + + void enableAuthorizer(bool enable); + + int pageSize(); + + sqlite3* m_db; + int m_lastError; + int m_pageSize; + + bool m_transactionInProgress; + + Mutex m_authorizerLock; + RefPtr<SQLiteAuthorizer> m_authorizer; + + Mutex m_lockingMutex; + ThreadIdentifier m_openingThread; + +}; // class SQLiteDatabase + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp new file mode 100644 index 0000000..ac96034 --- /dev/null +++ b/WebCore/platform/sql/SQLiteStatement.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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 "SQLiteStatement.h" + +#include "Logging.h" +#include "SQLValue.h" +#include <sqlite3.h> +#include <wtf/Assertions.h> + +namespace WebCore { + +#if SQLITE_VERSION_NUMBER < 3003009 + +// FIXME: This overload helps us compile with older versions of SQLite 3, but things like quotas will not work. +static inline int sqlite3_prepare16_v2(sqlite3* db, const void* zSql, int nBytes, sqlite3_stmt** ppStmt, const void** pzTail) +{ + return sqlite3_prepare16(db, zSql, nBytes, ppStmt, pzTail); +} + +#endif + +SQLiteStatement::SQLiteStatement(SQLiteDatabase& db, const String& sql) + : m_database(db) + , m_query(sql) + , m_statement(0) +#ifndef NDEBUG + , m_isPrepared(false) +#endif +{ +} + +SQLiteStatement::~SQLiteStatement() +{ + finalize(); +} + +int SQLiteStatement::prepare() +{ + ASSERT(!m_isPrepared); + const void* tail; + LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); + int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.charactersWithNullTermination(), -1, &m_statement, &tail); + if (error != SQLITE_OK) + LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); +#ifndef NDEBUG + m_isPrepared = error == SQLITE_OK; +#endif + return error; +} + +int SQLiteStatement::step() +{ + ASSERT(m_isPrepared); + if (!m_statement) + return SQLITE_OK; + LOG(SQLDatabase, "SQL - step - %s", m_query.ascii().data()); + int error = sqlite3_step(m_statement); + if (error != SQLITE_DONE && error != SQLITE_ROW) { + LOG(SQLDatabase, "sqlite3_step failed (%i)\nQuery - %s\nError - %s", + error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); + } + return error; +} + +int SQLiteStatement::finalize() +{ +#ifndef NDEBUG + m_isPrepared = false; +#endif + if (!m_statement) + return SQLITE_OK; + LOG(SQLDatabase, "SQL - finalize - %s", m_query.ascii().data()); + int result = sqlite3_finalize(m_statement); + m_statement = 0; + return result; +} + +int SQLiteStatement::reset() +{ + ASSERT(m_isPrepared); + if (!m_statement) + return SQLITE_OK; + LOG(SQLDatabase, "SQL - reset - %s", m_query.ascii().data()); + return sqlite3_reset(m_statement); +} + +bool SQLiteStatement::executeCommand() +{ + if (!m_statement && prepare() != SQLITE_OK) + return false; + ASSERT(m_isPrepared); + if (step() != SQLITE_DONE) { + finalize(); + return false; + } + finalize(); + return true; +} + +bool SQLiteStatement::returnsAtLeastOneResult() +{ + if (!m_statement && prepare() != SQLITE_OK) + return false; + ASSERT(m_isPrepared); + if (step() != SQLITE_ROW) { + finalize(); + return false; + } + finalize(); + return true; + +} + +int SQLiteStatement::bindBlob(int index, const void* blob, int size) +{ + ASSERT(m_isPrepared); + ASSERT(index > 0); + ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); + ASSERT(blob); + ASSERT(size >= 0); + + if (!m_statement) + return SQLITE_ERROR; + + return sqlite3_bind_blob(m_statement, index, blob, size, SQLITE_TRANSIENT); +} + +int SQLiteStatement::bindText(int index, const String& text) +{ + ASSERT(m_isPrepared); + ASSERT(index > 0); + ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); + + // String::characters() returns 0 for the empty string, which SQLite + // treats as a null, so we supply a non-null pointer for that case. + UChar anyCharacter = 0; + const UChar* characters; + if (text.isEmpty() && !text.isNull()) + characters = &anyCharacter; + else + characters = text.characters(); + + return sqlite3_bind_text16(m_statement, index, characters, sizeof(UChar) * text.length(), SQLITE_TRANSIENT); +} + + +int SQLiteStatement::bindInt64(int index, int64_t integer) +{ + ASSERT(m_isPrepared); + ASSERT(index > 0); + ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); + + return sqlite3_bind_int64(m_statement, index, integer); +} + +int SQLiteStatement::bindDouble(int index, double number) +{ + ASSERT(m_isPrepared); + ASSERT(index > 0); + ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); + + return sqlite3_bind_double(m_statement, index, number); +} + +int SQLiteStatement::bindNull(int index) +{ + ASSERT(m_isPrepared); + ASSERT(index > 0); + ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); + + return sqlite3_bind_null(m_statement, 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; +} + +unsigned SQLiteStatement::bindParameterCount() const +{ + ASSERT(m_isPrepared); + if (!m_statement) + return 0; + return sqlite3_bind_parameter_count(m_statement); +} + +int SQLiteStatement::columnCount() +{ + ASSERT(m_isPrepared); + if (!m_statement) + return 0; + return sqlite3_data_count(m_statement); +} + +String SQLiteStatement::getColumnName(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return String(); + if (columnCount() <= col) + return String(); + return String(reinterpret_cast<const UChar*>(sqlite3_column_name16(m_statement, col))); +} + +SQLValue SQLiteStatement::getColumnValue(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return SQLValue(); + if (columnCount() <= col) + return SQLValue(); + + // SQLite is typed per value. optional column types are + // "(mostly) ignored" + sqlite3_value* value = sqlite3_column_value(m_statement, 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)); + case SQLITE_BLOB: // SQLValue and JS don't represent blobs, so use TEXT -case + case SQLITE_TEXT: + return SQLValue(String(reinterpret_cast<const UChar*>(sqlite3_value_text16(value)))); + case SQLITE_NULL: + return SQLValue(); + default: + break; + } + ASSERT_NOT_REACHED(); + return SQLValue(); +} + +String SQLiteStatement::getColumnText(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return String(); + if (columnCount() <= col) + return String(); + return String(reinterpret_cast<const UChar*>(sqlite3_column_text16(m_statement, col))); +} + +double SQLiteStatement::getColumnDouble(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return 0.0; + if (columnCount() <= col) + return 0.0; + return sqlite3_column_double(m_statement, col); +} + +int SQLiteStatement::getColumnInt(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return 0; + if (columnCount() <= col) + return 0; + return sqlite3_column_int(m_statement, col); +} + +int64_t SQLiteStatement::getColumnInt64(int col) +{ + ASSERT(col >= 0); + if (!m_statement) + if (prepareAndStep() != SQLITE_ROW) + return 0; + if (columnCount() <= col) + return 0; + return sqlite3_column_int64(m_statement, col); +} + +void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result) +{ + ASSERT(col >= 0); + + if (!m_statement && prepareAndStep() != SQLITE_ROW) { + result.clear(); + return; + } + + if (columnCount() <= col) { + result.clear(); + return; + } + + const void* blob = sqlite3_column_blob(m_statement, col); + 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] = ((const unsigned char*)blob)[i]; +} + +const void* SQLiteStatement::getColumnBlob(int col, int& size) +{ + ASSERT(col >= 0); + + size = 0; + + if (finalize() != SQLITE_OK) + LOG(SQLDatabase, "Finalize failed"); + if (prepare() != SQLITE_OK) { + LOG(SQLDatabase, "Prepare failed"); + return 0; + } + if (step() != SQLITE_ROW) { + LOG(SQLDatabase, "Step wasn't a row"); + return 0; + } + + 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; +} + +bool SQLiteStatement::returnTextResults(int col, Vector<String>& v) +{ + ASSERT(col >= 0); + + v.clear(); + + if (m_statement) + finalize(); + if (prepare() != SQLITE_OK) + return false; + + while (step() == SQLITE_ROW) + v.append(getColumnText(col)); + bool result = true; + if (m_database.lastError() != SQLITE_DONE) { + result = false; + LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); + } + finalize(); + return result; +} + +bool SQLiteStatement::returnIntResults(int col, Vector<int>& v) +{ + v.clear(); + + if (m_statement) + finalize(); + if (prepare() != SQLITE_OK) + return false; + + while (step() == SQLITE_ROW) + v.append(getColumnInt(col)); + bool result = true; + if (m_database.lastError() != SQLITE_DONE) { + result = false; + LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); + } + finalize(); + return result; +} + +bool SQLiteStatement::returnInt64Results(int col, Vector<int64_t>& v) +{ + v.clear(); + + if (m_statement) + finalize(); + if (prepare() != SQLITE_OK) + return false; + + while (step() == SQLITE_ROW) + v.append(getColumnInt64(col)); + bool result = true; + if (m_database.lastError() != SQLITE_DONE) { + result = false; + LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); + } + finalize(); + return result; +} + +bool SQLiteStatement::returnDoubleResults(int col, Vector<double>& v) +{ + v.clear(); + + if (m_statement) + finalize(); + if (prepare() != SQLITE_OK) + return false; + + while (step() == SQLITE_ROW) + v.append(getColumnDouble(col)); + bool result = true; + if (m_database.lastError() != SQLITE_DONE) { + result = false; + LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); + } + finalize(); + return result; +} + +bool SQLiteStatement::isExpired() +{ + return !m_statement || sqlite3_expired(m_statement); +} + +} // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteStatement.h b/WebCore/platform/sql/SQLiteStatement.h new file mode 100644 index 0000000..5df4731 --- /dev/null +++ b/WebCore/platform/sql/SQLiteStatement.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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. + */ + +#ifndef SQLiteStatement_h +#define SQLiteStatement_h + +#include "SQLiteDatabase.h" + +struct sqlite3_stmt; + +namespace WebCore { + +class SQLValue; + +class SQLiteStatement : public Noncopyable { +public: + SQLiteStatement(SQLiteDatabase&, const String&); + ~SQLiteStatement(); + + int prepare(); + int bindBlob(int index, const void* blob, int size); + int bindText(int index, const String&); + int bindInt64(int index, int64_t); + int bindDouble(int index, double); + int bindNull(int index); + int bindValue(int index, const SQLValue&); + unsigned bindParameterCount() const; + + int step(); + int finalize(); + 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(); + + // prepares, steps, and finalizes. + // returns true is step() returns SQLITE_ROW + // returns false otherwise + bool returnsAtLeastOneResult(); + + bool isExpired(); + + // Returns -1 on last-step failing. Otherwise, returns number of rows + // returned in the last step() + int columnCount(); + + String getColumnName(int col); + SQLValue getColumnValue(int col); + String getColumnText(int col); + double getColumnDouble(int col); + int getColumnInt(int col); + int64_t getColumnInt64(int col); + const void* getColumnBlob(int col, int& size); + void getColumnBlobAsVector(int col, Vector<char>&); + + 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; } + +private: + SQLiteDatabase& m_database; + String m_query; + sqlite3_stmt* m_statement; +#ifndef NDEBUG + bool m_isPrepared; +#endif +}; + +} // namespace WebCore + +#endif // SQLiteStatement_h diff --git a/WebCore/platform/sql/SQLiteTransaction.cpp b/WebCore/platform/sql/SQLiteTransaction.cpp new file mode 100644 index 0000000..5018f5a --- /dev/null +++ b/WebCore/platform/sql/SQLiteTransaction.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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 "SQLiteTransaction.h" + +#include "SQLiteDatabase.h" + +namespace WebCore { + +SQLiteTransaction::SQLiteTransaction(SQLiteDatabase& db) + : m_db(db) + , m_inProgress(false) +{ +} + +SQLiteTransaction::~SQLiteTransaction() +{ + if (m_inProgress) + rollback(); +} + +void SQLiteTransaction::begin() +{ + if (!m_inProgress) { + ASSERT(!m_db.m_transactionInProgress); + m_inProgress = m_db.executeCommand("BEGIN;"); + m_db.m_transactionInProgress = true; + } +} + +void SQLiteTransaction::commit() +{ + if (m_inProgress) { + ASSERT(m_db.m_transactionInProgress); + m_db.executeCommand("COMMIT;"); + m_inProgress = false; + m_db.m_transactionInProgress = false; + } +} + +void SQLiteTransaction::rollback() +{ + if (m_inProgress) { + ASSERT(m_db.m_transactionInProgress); + m_db.executeCommand("ROLLBACK;"); + m_inProgress = false; + m_db.m_transactionInProgress = false; + } +} + +void SQLiteTransaction::stop() +{ + m_inProgress = false; + m_db.m_transactionInProgress = false; +} + +} // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteTransaction.h b/WebCore/platform/sql/SQLiteTransaction.h new file mode 100644 index 0000000..cf5a180 --- /dev/null +++ b/WebCore/platform/sql/SQLiteTransaction.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * 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. + */ + +#ifndef SQLiteTransaction_h +#define SQLiteTransaction_h + +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class SQLiteDatabase; + +class SQLiteTransaction : public Noncopyable +{ +public: + SQLiteTransaction(SQLiteDatabase& db); + ~SQLiteTransaction(); + + void begin(); + void commit(); + void rollback(); + void stop(); + + bool inProgress() const { return m_inProgress; } +private: + SQLiteDatabase& m_db; + bool m_inProgress; + +}; + +} // namespace WebCore + +#endif // SQLiteTransation_H + |