18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 221939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2010 Google Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 5967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * modification, are permitted provided that the following conditions are 6967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 8967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * * Redistributions of source code must retain the above copyright 9967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * notice, this list of conditions and the following disclaimer. 10967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * * Redistributions in binary form must reproduce the above 11967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * copyright notice, this list of conditions and the following disclaimer 12967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * in the documentation and/or other materials provided with the 13967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * distribution. 14967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * * Neither the name of Google Inc. nor the names of its 15967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * contributors may be used to endorse or promote products derived from 16967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * this software without specific prior written permission. 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 18967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 3221939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "SQLTransactionSync.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 348ccf722629b08f2a06b2cadbdc3d0c9dc885e25dBen Murdoch#if ENABLE(DATABASE) 358ccf722629b08f2a06b2cadbdc3d0c9dc885e25dBen Murdoch 36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "DatabaseAuthorizer.h" 3721939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "DatabaseSync.h" 3821939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "PlatformString.h" 39967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "SQLException.h" 4021939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "SQLResultSet.h" 41967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "SQLStatementSync.h" 42967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "SQLTransactionClient.h" 4321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "SQLTransactionSyncCallback.h" 4421939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "SQLValue.h" 45967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "SQLiteTransaction.h" 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ScriptExecutionContext.h" 4721939df44de1705786c545cd1bf519d47250322dBen Murdoch#include <wtf/PassRefPtr.h> 4821939df44de1705786c545cd1bf519d47250322dBen Murdoch#include <wtf/RefPtr.h> 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 5221939df44de1705786c545cd1bf519d47250322dBen MurdochPassRefPtr<SQLTransactionSync> SQLTransactionSync::create(DatabaseSync* db, PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5421939df44de1705786c545cd1bf519d47250322dBen Murdoch return adoptRef(new SQLTransactionSync(db, callback, readOnly)); 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 5721939df44de1705786c545cd1bf519d47250322dBen MurdochSQLTransactionSync::SQLTransactionSync(DatabaseSync* db, PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly) 5821939df44de1705786c545cd1bf519d47250322dBen Murdoch : m_database(db) 5921939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_callback(callback) 6021939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_readOnly(readOnly) 61967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch , m_modifiedDatabase(false) 62e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block , m_transactionClient(adoptPtr(new SQLTransactionClient())) 63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 6421939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6721939df44de1705786c545cd1bf519d47250322dBen MurdochSQLTransactionSync::~SQLTransactionSync() 68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 6921939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 70967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_sqliteTransaction && m_sqliteTransaction->inProgress()) 71967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch rollback(); 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 74967717af5423377c967781471ee106e2bb4e11c8Ben MurdochPassRefPtr<SQLResultSet> SQLTransactionSync::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionCode& ec) 7521939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 7621939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 77967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_database->opened()) { 78967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ec = SQLException::UNKNOWN_ERR; 79967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 80967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 81967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 82967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_database->versionMatchesExpected()) { 83967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ec = SQLException::VERSION_ERR; 84967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 85967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 86967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 87967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (sqlStatement.isEmpty()) 88967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 89967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int permissions = DatabaseAuthorizer::ReadWriteMask; 91f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!m_database->scriptExecutionContext()->allowDatabaseAccess()) 92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch permissions |= DatabaseAuthorizer::NoAccessMask; 93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else if (m_readOnly) 94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch permissions |= DatabaseAuthorizer::ReadOnlyMask; 95f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 96f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch SQLStatementSync statement(sqlStatement, arguments, permissions); 97967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 98967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->resetAuthorizer(); 99967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch bool retryStatement = true; 100967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch RefPtr<SQLResultSet> resultSet; 101967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch while (retryStatement) { 102967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch retryStatement = false; 103967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch resultSet = statement.execute(m_database.get(), ec); 104967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!resultSet) { 105967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_sqliteTransaction->wasRolledBackBySqlite()) 106967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 107967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 108967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (ec == SQLException::QUOTA_ERR) { 109967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_transactionClient->didExceedQuota(database())) { 110967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ec = 0; 111967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch retryStatement = true; 112967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } else 113967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 114967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 115967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 116967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 117967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 118967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_database->lastActionChangedDatabase()) { 119967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_modifiedDatabase = true; 120967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_transactionClient->didExecuteStatement(database()); 121967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 122967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 123967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return resultSet.release(); 124967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 125967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 126967717af5423377c967781471ee106e2bb4e11c8Ben MurdochExceptionCode SQLTransactionSync::begin() 127967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 128967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 129967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_database->opened()) 130967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return SQLException::UNKNOWN_ERR; 131967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 132967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 133967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 134967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // Set the maximum usage for this transaction if this transactions is not read-only. 135967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_readOnly) 136967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); 137967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 138967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(!m_sqliteTransaction); 139e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly)); 140967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 141967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->resetDeletes(); 142967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->disableAuthorizer(); 143967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction->begin(); 144967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->enableAuthorizer(); 145967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 146967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // Check if begin() succeeded. 147967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_sqliteTransaction->inProgress()) { 148967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 149967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction.clear(); 150967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return SQLException::DATABASE_ERR; 151967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 152967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 153967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 154967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 155967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 156967717af5423377c967781471ee106e2bb4e11c8Ben MurdochExceptionCode SQLTransactionSync::execute() 157967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 158967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 159dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_database->opened() || (m_callback && !m_callback->handleEvent(this))) { 160967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_callback = 0; 161967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return SQLException::UNKNOWN_ERR; 162967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 163967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 164967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_callback = 0; 165967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return 0; 166967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 167967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 168967717af5423377c967781471ee106e2bb4e11c8Ben MurdochExceptionCode SQLTransactionSync::commit() 169967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 170967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 171967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!m_database->opened()) 172967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return SQLException::UNKNOWN_ERR; 173967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 174967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(m_sqliteTransaction); 175967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 176967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->disableAuthorizer(); 177967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction->commit(); 178967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->enableAuthorizer(); 179967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 180967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // If the commit failed, the transaction will still be marked as "in progress" 181967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_sqliteTransaction->inProgress()) 182967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return SQLException::DATABASE_ERR; 183967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 184967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction.clear(); 185967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 186967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // Vacuum the database if anything was deleted. 187967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_database->hadDeletes()) 188967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->incrementalVacuumIfNeeded(); 189967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 190967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // The commit was successful. If the transaction modified this database, notify the delegates. 191967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_modifiedDatabase) 192967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_transactionClient->didCommitWriteTransaction(database()); 193967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 19421939df44de1705786c545cd1bf519d47250322dBen Murdoch return 0; 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1968ccf722629b08f2a06b2cadbdc3d0c9dc885e25dBen Murdoch 197967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid SQLTransactionSync::rollback() 198967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 199967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(m_database->scriptExecutionContext()->isContextThread()); 200967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->disableAuthorizer(); 201967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (m_sqliteTransaction) { 202967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction->rollback(); 203967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_sqliteTransaction.clear(); 204967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 205967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch m_database->enableAuthorizer(); 206967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 207967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 208967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 209967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 21021939df44de1705786c545cd1bf519d47250322dBen Murdoch} // namespace WebCore 21121939df44de1705786c545cd1bf519d47250322dBen Murdoch 2128ccf722629b08f2a06b2cadbdc3d0c9dc885e25dBen Murdoch#endif // ENABLE(DATABASE) 213