summaryrefslogtreecommitdiff
path: root/storage/mozStorageStatementData.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mozStorageStatementData.h')
-rw-r--r--storage/mozStorageStatementData.h150
1 files changed, 150 insertions, 0 deletions
diff --git a/storage/mozStorageStatementData.h b/storage/mozStorageStatementData.h
new file mode 100644
index 0000000000..8baaf2fa73
--- /dev/null
+++ b/storage/mozStorageStatementData.h
@@ -0,0 +1,150 @@
+/* -*- 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 "nsAutoPtr.h"
+#include "nsTArray.h"
+#include "nsIEventTarget.h"
+#include "MainThreadUtils.h"
+
+#include "mozStorageBindingParamsArray.h"
+#include "mozIStorageBaseStatement.h"
+#include "mozStorageConnection.h"
+#include "StorageBaseStatementInternal.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)
+ , mStatementOwner(aStatementOwner)
+ {
+ NS_PRECONDITION(mStatementOwner, "Must have a statement owner!");
+ }
+ StatementData(const StatementData &aSource)
+ : mStatement(aSource.mStatement)
+ , mParamsArray(aSource.mParamsArray)
+ , mStatementOwner(aSource.mStatementOwner)
+ {
+ NS_PRECONDITION(mStatementOwner, "Must have a statement owner!");
+ }
+ StatementData()
+ : mStatement(nullptr)
+ {
+ }
+ ~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(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);
+ 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()
+ {
+ NS_PRECONDITION(mStatementOwner, "Must have a statement owner!");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsIEventTarget> asyncThread =
+ mStatementOwner->getOwner()->getAsyncExecutionTarget();
+ // It's possible that we are shutting down the async thread, and this
+ // method would return nullptr as a result.
+ if (asyncThread) {
+ bool onAsyncThread;
+ NS_ASSERTION(NS_SUCCEEDED(asyncThread->IsOnCurrentThread(&onAsyncThread)) && onAsyncThread,
+ "This should only be running on the async thread!");
+ }
+ }
+#endif
+ // 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;
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+private:
+ sqlite3_stmt *mStatement;
+ RefPtr<BindingParamsArray> mParamsArray;
+
+ /**
+ * 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