ResultStatement.h (5580B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef DOM_FS_PARENT_RESULTSTATEMENT_H_ 8 #define DOM_FS_PARENT_RESULTSTATEMENT_H_ 9 10 #include "FileSystemParentTypes.h" 11 #include "mozIStorageStatement.h" 12 #include "mozilla/dom/FileSystemTypes.h" 13 #include "mozilla/dom/quota/QuotaCommon.h" 14 #include "mozilla/dom/quota/ResultExtensions.h" 15 #include "nsCOMPtr.h" 16 #include "nsString.h" 17 18 class mozIStorageConnection; 19 20 namespace mozilla::dom::fs { 21 22 using Column = uint32_t; 23 24 using ResultConnection = nsCOMPtr<mozIStorageConnection>; 25 26 /** 27 * @brief ResultStatement 28 * - provides error monad Result<T, E> compatible interface to the lower level 29 * error code-based statement implementation in order to enable remote 30 * debugging with error stack traces 31 * - converts between OPFS internal data types and the generic data types of 32 * the lower level implementation 33 * - provides a customization point for requests aimed at the lower level 34 * implementation allowing for example to remap errors or implement mocks 35 */ 36 class ResultStatement { 37 public: 38 using underlying_t = nsCOMPtr<mozIStorageStatement>; 39 40 explicit ResultStatement(underlying_t aStmt) : mStmt(std::move(aStmt)) {} 41 42 ResultStatement(const ResultStatement& aOther) 43 : ResultStatement(aOther.mStmt) {} 44 45 ResultStatement(ResultStatement&& aOther) noexcept 46 : ResultStatement(std::move(aOther.mStmt)) {} 47 48 ResultStatement& operator=(const ResultStatement& aOther) = default; 49 50 ResultStatement& operator=(ResultStatement&& aOther) noexcept { 51 mStmt = std::move(aOther.mStmt); 52 return *this; 53 } 54 55 static Result<ResultStatement, QMResult> Create( 56 const ResultConnection& aConnection, const nsACString& aSQLStatement); 57 58 // XXX Consider moving all these "inline" methods into a separate file 59 // called ResultStatementInlines.h. ResultStatement.h wouldn't have to then 60 // include ResultExtensions.h, QuotaCommon.h and mozIStorageStatement.h 61 // which are quite large and should be preferable only included from cpp 62 // files or special headers like ResultStatementInlines.h. So in the end, 63 // other headers would include ResultStatement.h only and other cpp files 64 // would include ResultStatementInlines.h. See also IndedexDababase.h and 65 // IndexedDatabaseInlines.h to see how it's done. 66 67 inline nsresult BindEntryIdByName(const nsACString& aField, 68 const EntryId& aValue) { 69 return mStmt->BindUTF8StringAsBlobByName(aField, aValue); 70 } 71 72 inline nsresult BindFileIdByName(const nsACString& aField, 73 const FileId& aValue) { 74 return mStmt->BindUTF8StringAsBlobByName(aField, aValue.Value()); 75 } 76 77 inline nsresult BindContentTypeByName(const nsACString& aField, 78 const ContentType& aValue) { 79 if (aValue.IsVoid()) { 80 return mStmt->BindNullByName(aField); 81 } 82 83 return mStmt->BindUTF8StringByName(aField, aValue); 84 } 85 86 inline nsresult BindNameByName(const nsACString& aField, const Name& aValue) { 87 return mStmt->BindStringAsBlobByName(aField, aValue); 88 } 89 90 inline nsresult BindPageNumberByName(const nsACString& aField, 91 PageNumber aValue) { 92 return mStmt->BindInt32ByName(aField, aValue); 93 } 94 95 inline nsresult BindUsageByName(const nsACString& aField, Usage aValue) { 96 return mStmt->BindInt64ByName(aField, aValue); 97 } 98 99 inline nsresult BindBooleanByName(const nsACString& aField, bool aValue) { 100 return mStmt->BindInt32ByName(aField, aValue ? 1 : 0); 101 } 102 103 inline Result<bool, QMResult> GetBooleanByColumn(Column aColumn) { 104 int32_t value = 0; 105 QM_TRY(QM_TO_RESULT(mStmt->GetInt32(aColumn, &value))); 106 107 return 0 != value; 108 } 109 110 inline Result<ContentType, QMResult> GetContentTypeByColumn(Column aColumn) { 111 ContentType value; 112 QM_TRY(QM_TO_RESULT(mStmt->GetUTF8String(aColumn, value))); 113 114 return value; 115 } 116 117 inline Result<EntryId, QMResult> GetEntryIdByColumn(Column aColumn) { 118 EntryId value; 119 QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsUTF8String(aColumn, value))); 120 121 return value; 122 } 123 124 inline Result<FileId, QMResult> GetFileIdByColumn(Column aColumn) { 125 nsCString value; 126 QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsUTF8String(aColumn, value))); 127 128 return FileId(std::move(value)); 129 } 130 131 inline Result<Name, QMResult> GetNameByColumn(Column aColumn) { 132 Name value; 133 QM_TRY(QM_TO_RESULT(mStmt->GetBlobAsString(aColumn, value))); 134 135 return value; 136 } 137 138 inline Result<Usage, QMResult> GetUsageByColumn(Column aColumn) { 139 Usage value = 0; 140 QM_TRY(QM_TO_RESULT(mStmt->GetInt64(aColumn, &value))); 141 142 return value; 143 } 144 145 inline bool IsNullByColumn(Column aColumn) const { 146 bool value = mStmt->IsNull(aColumn); 147 148 return value; 149 } 150 151 inline nsresult Execute() { return mStmt->Execute(); } 152 153 inline Result<bool, QMResult> ExecuteStep() { 154 bool hasEntries = false; 155 QM_TRY(QM_TO_RESULT(mStmt->ExecuteStep(&hasEntries))); 156 157 return hasEntries; 158 } 159 160 inline Result<bool, QMResult> YesOrNoQuery() { 161 bool hasEntries = false; 162 QM_TRY(QM_TO_RESULT(mStmt->ExecuteStep(&hasEntries))); 163 MOZ_ALWAYS_TRUE(hasEntries); 164 return GetBooleanByColumn(0u); 165 } 166 167 private: 168 underlying_t mStmt; 169 }; 170 171 } // namespace mozilla::dom::fs 172 173 #endif // DOM_FS_PARENT_RESULTSTATEMENT_H_