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