summaryrefslogtreecommitdiffstats
path: root/storage/mozStorageStatementData.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mozStorageStatementData.h')
-rw-r--r--storage/mozStorageStatementData.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/storage/mozStorageStatementData.h b/storage/mozStorageStatementData.h
new file mode 100644
index 0000000000..1008496671
--- /dev/null
+++ b/storage/mozStorageStatementData.h
@@ -0,0 +1,143 @@
+/* -*- 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