summaryrefslogtreecommitdiffstats
path: root/dom/fs/parent/ResultStatement.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/fs/parent/ResultStatement.h')
-rw-r--r--dom/fs/parent/ResultStatement.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/dom/fs/parent/ResultStatement.h b/dom/fs/parent/ResultStatement.h
new file mode 100644
index 0000000000..3e532f3ae4
--- /dev/null
+++ b/dom/fs/parent/ResultStatement.h
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 DOM_FS_PARENT_RESULTSTATEMENT_H_
+#define DOM_FS_PARENT_RESULTSTATEMENT_H_
+
+#include "FileSystemParentTypes.h"
+#include "mozIStorageStatement.h"
+#include "mozilla/dom/FileSystemTypes.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
+#include "mozilla/dom/quota/ResultExtensions.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+class mozIStorageConnection;
+
+namespace mozilla::dom::fs {
+
+using Column = uint32_t;
+
+using ResultConnection = nsCOMPtr<mozIStorageConnection>;
+
+/**
+ * @brief ResultStatement
+ * - provides error monad Result<T, E> compatible interface to the lower level
+ * error code-based statement implementation in order to enable remote
+ * debugging with error stack traces
+ * - converts between OPFS internal data types and the generic data types of
+ * the lower level implementation
+ * - provides a customization point for requests aimed at the lower level
+ * implementation allowing for example to remap errors or implement mocks
+ */
+class ResultStatement {
+ public:
+ using underlying_t = nsCOMPtr<mozIStorageStatement>;
+
+ explicit ResultStatement(underlying_t aStmt) : mStmt(std::move(aStmt)) {}
+
+ ResultStatement(const ResultStatement& aOther)
+ : ResultStatement(aOther.mStmt) {}
+
+ ResultStatement(ResultStatement&& aOther) noexcept
+ : ResultStatement(std::move(aOther.mStmt)) {}
+
+ ResultStatement& operator=(const ResultStatement& aOther) = default;
+
+ ResultStatement& operator=(ResultStatement&& aOther) noexcept {
+ mStmt = std::move(aOther.mStmt);
+ return *this;
+ }
+
+ static Result<ResultStatement, QMResult> Create(
+ const ResultConnection& aConnection, const nsACString& aSQLStatement);
+
+ // XXX Consider moving all these "inline" methods into a separate file
+ // called ResultStatementInlines.h. ResultStatement.h wouldn't have to then
+ // include ResultExtensions.h, QuotaCommon.h and mozIStorageStatement.h
+ // which are quite large and should be preferable only included from cpp
+ // files or special headers like ResultStatementInlines.h. So in the end,
+ // other headers would include ResultStatement.h only and other cpp files
+ // would include ResultStatementInlines.h. See also IndedexDababase.h and
+ // IndexedDatabaseInlines.h to see how it's done.
+
+ inline nsresult BindEntryIdByName(const nsACString& aField,
+ const EntryId& aValue) {
+ return mStmt->BindUTF8StringAsBlobByName(aField, aValue);
+ }
+
+ inline nsresult BindFileIdByName(const nsACString& aField,
+ const FileId& aValue) {
+ return mStmt->BindUTF8StringAsBlobByName(aField, aValue.Value());
+ }
+
+ inline nsresult BindContentTypeByName(const nsACString& aField,
+ const ContentType& aValue) {
+ if (aValue.IsVoid()) {
+ return mStmt->BindNullByName(aField);
+ }
+
+ return mStmt->BindUTF8StringByName(aField, aValue);
+ }
+
+ inline nsresult BindNameByName(const nsACString& aField, const Name& aValue) {
+ return mStmt->BindStringAsBlobByName(aField, aValue);
+ }
+
+ inline nsresult BindPageNumberByName(const nsACString& aField,
+ PageNumber aValue) {
+ return mStmt->BindInt32ByName(aField, aValue);
+ }
+
+ inline nsresult BindUsageByName(const nsACString& aField, Usage aValue) {
+ return mStmt->BindInt64ByName(aField, aValue);
+ }
+
+ inline nsresult BindBooleanByName(const nsACString& aField, bool aValue) {
+ return mStmt->BindInt32ByName(aField, aValue ? 1 : 0);
+ }
+
+ inline Result<bool, QMResult> GetBooleanByColumn(Column aColumn) {
+ int32_t value = 0;
+ QM_TRY(QM_TO_RESULT(mStmt->GetInt32(aColumn, &value)));
+
+ return 0 != value;
+ }
+
+ inline Result<ContentType, QMResult> GetContentTypeByColumn(Column aColumn) {
+ ContentType value;
+ QM_TRY(QM_TO_RESULT(mStmt->GetUTF8String(aColumn, value)));
+
+ return value;
+ }
+
+ inline Result<EntryId, QMResult> GetEntryIdByColumn(Column aColumn) {
+ EntryId value;
+ QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsUTF8String(aColumn, value)));
+
+ return value;
+ }
+
+ inline Result<FileId, QMResult> GetFileIdByColumn(Column aColumn) {
+ nsCString value;
+ QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsUTF8String(aColumn, value)));
+
+ return FileId(std::move(value));
+ }
+
+ inline Result<Name, QMResult> GetNameByColumn(Column aColumn) {
+ Name value;
+ QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsString(aColumn, value)));
+
+ return value;
+ }
+
+ inline Result<Usage, QMResult> GetUsageByColumn(Column aColumn) {
+ Usage value = 0;
+ QM_TRY(QM_TO_RESULT(mStmt->GetInt64(aColumn, &value)));
+
+ return value;
+ }
+
+ inline bool IsNullByColumn(Column aColumn) const {
+ bool value = mStmt->IsNull(aColumn);
+
+ return value;
+ }
+
+ inline nsresult Execute() { return mStmt->Execute(); }
+
+ inline Result<bool, QMResult> ExecuteStep() {
+ bool hasEntries = false;
+ QM_TRY(QM_TO_RESULT(mStmt->ExecuteStep(&hasEntries)));
+
+ return hasEntries;
+ }
+
+ inline Result<bool, QMResult> YesOrNoQuery() {
+ bool hasEntries = false;
+ QM_TRY(QM_TO_RESULT(mStmt->ExecuteStep(&hasEntries)));
+ MOZ_ALWAYS_TRUE(hasEntries);
+ return GetBooleanByColumn(0u);
+ }
+
+ private:
+ underlying_t mStmt;
+};
+
+} // namespace mozilla::dom::fs
+
+#endif // DOM_FS_PARENT_RESULTSTATEMENT_H_