mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
c9061686f8
Includes baddataDB.sqlite which is a copy of goodDB.sqlite but with what appears to be the row count inflated beyond the end of the file. This causes loading the database to succeed but queries to fail. This increments a scalar for every database open and for every database query where a query is the full execution of a statement from start to completion. If a statement is re-used then the scalar will be incremented once for each use. Differential Revision: https://phabricator.services.mozilla.com/D73938
144 lines
4.6 KiB
C++
144 lines
4.6 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
* vim: sw=2 ts=2 sts=2 et
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozStorageStatementData_h
|
|
#define mozStorageStatementData_h
|
|
|
|
#include "sqlite3.h"
|
|
|
|
#include "nsTArray.h"
|
|
#include "MainThreadUtils.h"
|
|
|
|
#include "mozStorageBindingParamsArray.h"
|
|
#include "mozStorageConnection.h"
|
|
#include "StorageBaseStatementInternal.h"
|
|
#include "mozStoragePrivateHelpers.h"
|
|
|
|
struct sqlite3_stmt;
|
|
|
|
namespace mozilla {
|
|
namespace storage {
|
|
|
|
class StatementData {
|
|
public:
|
|
StatementData(sqlite3_stmt* aStatement,
|
|
already_AddRefed<BindingParamsArray> aParamsArray,
|
|
StorageBaseStatementInternal* aStatementOwner)
|
|
: mStatement(aStatement),
|
|
mParamsArray(aParamsArray),
|
|
mQueryStatusRecorded(false),
|
|
mStatementOwner(aStatementOwner) {
|
|
MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
|
|
}
|
|
StatementData(const StatementData& aSource)
|
|
: mStatement(aSource.mStatement),
|
|
mParamsArray(aSource.mParamsArray),
|
|
mQueryStatusRecorded(false),
|
|
mStatementOwner(aSource.mStatementOwner) {
|
|
MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
|
|
}
|
|
StatementData() : mStatement(nullptr), mQueryStatusRecorded(false) {}
|
|
~StatementData() {
|
|
// We need to ensure that mParamsArray is released on the main thread,
|
|
// as the binding arguments may be XPConnect values, which are safe
|
|
// to release only on the main thread.
|
|
NS_ReleaseOnMainThread("StatementData::mParamsArray",
|
|
mParamsArray.forget());
|
|
}
|
|
|
|
/**
|
|
* Return the sqlite statement, fetching it from the storage statement. In
|
|
* the case of AsyncStatements this may actually create the statement
|
|
*/
|
|
inline int getSqliteStatement(sqlite3_stmt** _stmt) {
|
|
if (!mStatement) {
|
|
int rc = mStatementOwner->getAsyncStatement(&mStatement);
|
|
MaybeRecordQueryStatus(rc);
|
|
NS_ENSURE_TRUE(rc == SQLITE_OK, rc);
|
|
}
|
|
*_stmt = mStatement;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
operator BindingParamsArray*() const { return mParamsArray; }
|
|
|
|
/**
|
|
* NULLs out our sqlite3_stmt (it is held by the owner) after reseting it and
|
|
* clear all bindings to it. This is expected to occur on the async thread.
|
|
*/
|
|
inline void reset() {
|
|
MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
|
|
// In the AsyncStatement case we may never have populated mStatement if the
|
|
// AsyncExecuteStatements got canceled or a failure occurred in constructing
|
|
// the statement.
|
|
if (mStatement) {
|
|
(void)::sqlite3_reset(mStatement);
|
|
(void)::sqlite3_clear_bindings(mStatement);
|
|
mStatement = nullptr;
|
|
|
|
if (!mQueryStatusRecorded) {
|
|
mStatementOwner->getOwner()->RecordQueryStatus(SQLITE_OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indicates if this statement has parameters to be bound before it is
|
|
* executed.
|
|
*
|
|
* @return true if the statement has parameters to bind against, false
|
|
* otherwise.
|
|
*/
|
|
inline bool hasParametersToBeBound() const { return !!mParamsArray; }
|
|
/**
|
|
* Indicates the number of implicit statements generated by this statement
|
|
* requiring a transaction for execution. For example a single statement
|
|
* with N BindingParams will execute N implicit staments.
|
|
*
|
|
* @return number of statements requiring a transaction for execution.
|
|
*
|
|
* @note In the case of AsyncStatements this may actually create the
|
|
* statement.
|
|
*/
|
|
inline uint32_t needsTransaction() {
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
// Be sure to use the getSqliteStatement helper, since sqlite3_stmt_readonly
|
|
// can only analyze prepared statements and AsyncStatements are prepared
|
|
// lazily.
|
|
sqlite3_stmt* stmt;
|
|
int rc = getSqliteStatement(&stmt);
|
|
if (SQLITE_OK != rc || ::sqlite3_stmt_readonly(stmt)) {
|
|
return 0;
|
|
}
|
|
return mParamsArray ? mParamsArray->length() : 1;
|
|
}
|
|
|
|
void MaybeRecordQueryStatus(int srv) {
|
|
if (mQueryStatusRecorded || !isErrorCode(srv)) {
|
|
return;
|
|
}
|
|
|
|
mStatementOwner->getOwner()->RecordQueryStatus(srv);
|
|
mQueryStatusRecorded = true;
|
|
}
|
|
|
|
private:
|
|
sqlite3_stmt* mStatement;
|
|
RefPtr<BindingParamsArray> mParamsArray;
|
|
bool mQueryStatusRecorded;
|
|
|
|
/**
|
|
* We hold onto a reference of the statement's owner so it doesn't get
|
|
* destroyed out from under us.
|
|
*/
|
|
nsCOMPtr<StorageBaseStatementInternal> mStatementOwner;
|
|
};
|
|
|
|
} // namespace storage
|
|
} // namespace mozilla
|
|
|
|
#endif // mozStorageStatementData_h
|