mozStorageStatementData.h (4481B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 sts=2 et 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 mozStorageStatementData_h 8 #define mozStorageStatementData_h 9 10 #include "sqlite3.h" 11 12 #include "nsTArray.h" 13 14 #include "mozStorageBindingParamsArray.h" 15 #include "mozStorageConnection.h" 16 #include "StorageBaseStatementInternal.h" 17 #include "mozStoragePrivateHelpers.h" 18 19 struct sqlite3_stmt; 20 21 namespace mozilla::storage { 22 23 class StatementData { 24 public: 25 StatementData(sqlite3_stmt* aStatement, 26 already_AddRefed<BindingParamsArray> aParamsArray, 27 StorageBaseStatementInternal* aStatementOwner) 28 : mStatement(aStatement), 29 mParamsArray(aParamsArray), 30 mQueryStatusRecorded(false), 31 mStatementOwner(aStatementOwner) { 32 MOZ_ASSERT(mStatementOwner, "Must have a statement owner!"); 33 } 34 StatementData(const StatementData& aSource) 35 : mStatement(aSource.mStatement), 36 mParamsArray(aSource.mParamsArray), 37 mQueryStatusRecorded(false), 38 mStatementOwner(aSource.mStatementOwner) { 39 MOZ_ASSERT(mStatementOwner, "Must have a statement owner!"); 40 } 41 StatementData() : mStatement(nullptr), mQueryStatusRecorded(false) {} 42 43 /** 44 * Return the sqlite statement, fetching it from the storage statement. In 45 * the case of AsyncStatements this may actually create the statement 46 */ 47 inline int getSqliteStatement(sqlite3_stmt** _stmt) { 48 if (!mStatement) { 49 int rc = mStatementOwner->getAsyncStatement(&mStatement); 50 MaybeRecordQueryStatus(rc); 51 NS_ENSURE_TRUE(rc == SQLITE_OK, rc); 52 } 53 *_stmt = mStatement; 54 return SQLITE_OK; 55 } 56 57 operator BindingParamsArray*() const { return mParamsArray; } 58 59 /** 60 * NULLs out our sqlite3_stmt (it is held by the owner) after reseting it and 61 * clear all bindings to it. This is expected to occur on the async thread. 62 */ 63 inline void reset() { 64 MOZ_ASSERT(mStatementOwner, "Must have a statement owner!"); 65 // In the AsyncStatement case we may never have populated mStatement if the 66 // AsyncExecuteStatements got canceled or a failure occurred in constructing 67 // the statement. 68 if (mStatement) { 69 (void)::sqlite3_reset(mStatement); 70 (void)::sqlite3_clear_bindings(mStatement); 71 mStatement = nullptr; 72 73 if (!mQueryStatusRecorded) { 74 mStatementOwner->getOwner()->RecordQueryStatus(SQLITE_OK); 75 } 76 } 77 } 78 79 /** 80 * Indicates if this statement has parameters to be bound before it is 81 * executed. 82 * 83 * @return true if the statement has parameters to bind against, false 84 * otherwise. 85 */ 86 inline bool hasParametersToBeBound() const { return !!mParamsArray; } 87 /** 88 * Indicates the number of implicit statements generated by this statement 89 * requiring a transaction for execution. For example a single statement 90 * with N BindingParams will execute N implicit staments. 91 * 92 * @return number of statements requiring a transaction for execution. 93 * 94 * @note In the case of AsyncStatements this may actually create the 95 * statement. 96 */ 97 inline uint32_t needsTransaction() { 98 MOZ_ASSERT(!NS_IsMainThread()); 99 // Be sure to use the getSqliteStatement helper, since sqlite3_stmt_readonly 100 // can only analyze prepared statements and AsyncStatements are prepared 101 // lazily. 102 sqlite3_stmt* stmt; 103 int rc = getSqliteStatement(&stmt); 104 if (SQLITE_OK != rc || ::sqlite3_stmt_readonly(stmt)) { 105 return 0; 106 } 107 return mParamsArray ? mParamsArray->length() : 1; 108 } 109 110 void MaybeRecordQueryStatus(int srv) { 111 if (mQueryStatusRecorded || !isErrorCode(srv)) { 112 return; 113 } 114 115 mStatementOwner->getOwner()->RecordQueryStatus(srv); 116 mQueryStatusRecorded = true; 117 } 118 119 private: 120 sqlite3_stmt* mStatement; 121 122 /** 123 * It's safe to release this on any thread, as it holds `BindingParams` that 124 * can only contain thread-safe derivates of `Variant_base`. 125 */ 126 RefPtr<BindingParamsArray> mParamsArray; 127 128 bool mQueryStatusRecorded; 129 130 /** 131 * We hold onto a reference of the statement's owner so it doesn't get 132 * destroyed out from under us. 133 */ 134 nsCOMPtr<StorageBaseStatementInternal> mStatementOwner; 135 }; 136 137 } // namespace mozilla::storage 138 139 #endif // mozStorageStatementData_h