StorageBaseStatementInternal.h (15213B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 sts=2 expandtab 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 mozilla_storage_StorageBaseStatementInternal_h_ 8 #define mozilla_storage_StorageBaseStatementInternal_h_ 9 10 #include "nsISupports.h" 11 #include "nsCOMPtr.h" 12 #include "mozStorageHelper.h" 13 14 struct sqlite3; 15 struct sqlite3_stmt; 16 class mozIStorageBindingParamsArray; 17 class mozIStorageBindingParams; 18 class mozIStorageStatementCallback; 19 class mozIStoragePendingStatement; 20 21 namespace mozilla { 22 namespace storage { 23 24 #define STORAGEBASESTATEMENTINTERNAL_IID \ 25 {0xd18856c9, 0xbf07, 0x4ae2, {0x94, 0x5b, 0x1a, 0xdd, 0x49, 0x19, 0x55, 0x2a}} 26 27 class Connection; 28 class StatementData; 29 30 class AsyncStatementFinalizer; 31 32 /** 33 * Implementation-only interface and shared logix mix-in corresponding to 34 * mozIStorageBaseStatement. Both Statement and AsyncStatement inherit from 35 * this. The interface aspect makes them look the same to implementation innards 36 * that aren't publicly accessible. The mix-in avoids code duplication in 37 * common implementations of mozIStorageBaseStatement, albeit with some minor 38 * performance/space overhead because we have to use defines to officially 39 * implement the methods on Statement/AsyncStatement (and proxy to this base 40 * class.) 41 */ 42 class StorageBaseStatementInternal : public nsISupports { 43 public: 44 NS_INLINE_DECL_STATIC_IID(STORAGEBASESTATEMENTINTERNAL_IID) 45 46 /** 47 * @return the connection that this statement belongs to. 48 */ 49 Connection* getOwner() { return mDBConnection; } 50 51 /** 52 * Return the asynchronous statement, creating it if required. 53 * 54 * This is for use by the asynchronous execution code for StatementData 55 * created by AsyncStatements. Statement internally uses this method to 56 * prepopulate StatementData with the sqlite3_stmt. 57 * 58 * @param[out] stmt 59 * The sqlite3_stmt for asynchronous use. 60 * @return The SQLite result code for creating the statement if created, 61 * SQLITE_OK if creation was not required. 62 */ 63 virtual int getAsyncStatement(sqlite3_stmt** _stmt) = 0; 64 65 /** 66 * Obtains the StatementData needed for asynchronous execution. 67 * 68 * This is for use by Connection to retrieve StatementData from statements 69 * when executeAsync is invoked. 70 * 71 * @param[out] _data 72 * A reference to a StatementData object that will be populated 73 * upon successful execution of this method. 74 * @return NS_OK if we were able to assemble the data, failure otherwise. 75 */ 76 virtual nsresult getAsynchronousStatementData(StatementData& _data) = 0; 77 78 /** 79 * Construct a new BindingParams to be owned by the provided binding params 80 * array. This method exists so that BindingParamsArray does not need 81 * factory logic to determine what type of BindingParams to instantiate. 82 * 83 * @param aOwner 84 * The binding params array to own the newly created binding params. 85 * @return The new mozIStorageBindingParams instance appropriate to the 86 * underlying statement type. 87 */ 88 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( 89 mozIStorageBindingParamsArray* aOwner) = 0; 90 91 protected: // mix-in bits are protected 92 StorageBaseStatementInternal(); 93 94 RefPtr<Connection> mDBConnection; 95 sqlite3* mNativeConnection; 96 97 /** 98 * Our asynchronous statement. 99 * 100 * For Statement this is populated by the first invocation to 101 * getAsyncStatement. 102 * 103 * For AsyncStatement, this is null at creation time and initialized by the 104 * async thread when it calls getAsyncStatement the first time the statement 105 * is executed. (Or in the event of badly formed SQL, every time.) 106 */ 107 sqlite3_stmt* mAsyncStatement; 108 109 /** 110 * Initiate asynchronous finalization by dispatching an event to the 111 * asynchronous thread to finalize mAsyncStatement. This acquires a reference 112 * to this statement and proxies it back to the connection's owning thread 113 * for release purposes. 114 * 115 * In the event the asynchronous thread is already gone or we otherwise fail 116 * to dispatch an event to it we failover to invoking internalAsyncFinalize 117 * directly. (That's what the asynchronous finalizer would have called.) 118 * 119 * @note You must not call this method from your destructor because its 120 * operation assumes we are still alive. Call internalAsyncFinalize 121 * directly in that case. 122 */ 123 void asyncFinalize(); 124 125 /** 126 * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists by 127 * attempting to dispatch to the asynchronous thread if available, finalizing 128 * on this thread if it is not. 129 * 130 * @note Call this from your destructor, call asyncFinalize otherwise. 131 */ 132 void destructorAsyncFinalize(); 133 134 NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray** _array); 135 NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback* aCallback, 136 mozIStoragePendingStatement** _stmt); 137 NS_IMETHOD EscapeStringForLIKE(const nsAString& aValue, char16_t aEscapeChar, 138 nsAString& _escapedString); 139 NS_IMETHOD EscapeUTF8StringForLIKE(const nsACString& aValue, char aEscapeChar, 140 nsACString& _escapedString); 141 142 // Needs access to internalAsyncFinalize 143 friend class AsyncStatementFinalizer; 144 }; 145 146 #define NS_DECL_STORAGEBASESTATEMENTINTERNAL \ 147 virtual Connection* getOwner(); \ 148 virtual int getAsyncStatement(sqlite3_stmt** _stmt) override; \ 149 virtual nsresult getAsynchronousStatementData(StatementData& _data) \ 150 override; \ 151 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \ 152 mozIStorageBindingParamsArray* aOwner) override; 153 154 /** 155 * Helper macro to implement the proxying implementations. Because we are 156 * implementing methods that are part of mozIStorageBaseStatement and the 157 * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't 158 * need to provide declaration support. 159 */ 160 #define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs) \ 161 NS_IMETHODIMP _class::_method _declArgs { \ 162 _optionalGuard return StorageBaseStatementInternal::_method _invokeArgs; \ 163 } 164 165 /** 166 * Define proxying implementation for the given _class. If a state invariant 167 * needs to be checked and an early return possibly performed, pass the clause 168 * to use as _optionalGuard. 169 */ 170 #define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \ 171 MIX_IMPL(_class, _optionalGuard, NewBindingParamsArray, \ 172 (mozIStorageBindingParamsArray * *_array), (_array)) \ 173 MIX_IMPL(_class, _optionalGuard, ExecuteAsync, \ 174 (mozIStorageStatementCallback * aCallback, \ 175 mozIStoragePendingStatement * *_stmt), \ 176 (aCallback, _stmt)) \ 177 MIX_IMPL(_class, _optionalGuard, EscapeStringForLIKE, \ 178 (const nsAString& aValue, char16_t aEscapeChar, \ 179 nsAString& _escapedString), \ 180 (aValue, aEscapeChar, _escapedString)) \ 181 MIX_IMPL(_class, _optionalGuard, EscapeUTF8StringForLIKE, \ 182 (const nsACString& aValue, char aEscapeChar, \ 183 nsACString& _escapedString), \ 184 (aValue, aEscapeChar, _escapedString)) 185 186 /** 187 * Name-building helper for BIND_GEN_IMPL. 188 */ 189 #define BIND_NAME_CONCAT(_nameBit, _concatBit) Bind##_nameBit##_concatBit 190 191 /** 192 * We have type-specific convenience methods for C++ implementations in 193 * two different forms; by index and by name. The following macro allows 194 * us to avoid having to define repetitive things by hand. 195 * 196 * Because of limitations of macros and our desire to avoid requiring special 197 * permutations for the null and blob cases (whose argument count varies), 198 * we require that the argument declarations and corresponding invocation 199 * usages are passed in. 200 * 201 * @param _class 202 * The class name. 203 * @param _guard 204 * The guard clause to inject. 205 * @param _declName 206 * The argument list (with parens) for the ByName variants. 207 * @param _declIndex 208 * The argument list (with parens) for the ByIndex variants. 209 * @param _invArgs 210 * The invocation argumment list. 211 */ 212 #define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \ 213 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName { \ 214 _guard mozIStorageBindingParams* params = getParams(); \ 215 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 216 return params->BIND_NAME_CONCAT(_name, ByName) _invArgs; \ 217 } \ 218 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex { \ 219 _guard mozIStorageBindingParams* params = getParams(); \ 220 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 221 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \ 222 } 223 224 /** 225 * Implement BindByName/BindByIndex for the given class. 226 * 227 * @param _class The class name. 228 * @param _optionalGuard The guard clause to inject. 229 */ 230 #define BIND_BASE_IMPLS(_class, _optionalGuard) \ 231 NS_IMETHODIMP _class::BindByName(const nsACString& aName, \ 232 nsIVariant* aValue) { \ 233 _optionalGuard mozIStorageBindingParams* params = getParams(); \ 234 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 235 return params->BindByName(aName, aValue); \ 236 } \ 237 NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, nsIVariant* aValue) { \ 238 _optionalGuard mozIStorageBindingParams* params = getParams(); \ 239 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 240 return params->BindByIndex(aIndex, aValue); \ 241 } 242 243 /** 244 * Define the various Bind*ByIndex, Bind*ByName stubs that just end up proxying 245 * to the params object. 246 */ 247 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \ 248 BIND_BASE_IMPLS(_class, _optionalGuard) \ 249 BIND_GEN_IMPL(_class, _optionalGuard, UTF8String, \ 250 (const nsACString& aWhere, const nsACString& aValue), \ 251 (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \ 252 BIND_GEN_IMPL(_class, _optionalGuard, String, \ 253 (const nsACString& aWhere, const nsAString& aValue), \ 254 (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue)) \ 255 BIND_GEN_IMPL(_class, _optionalGuard, Double, \ 256 (const nsACString& aWhere, double aValue), \ 257 (uint32_t aWhere, double aValue), (aWhere, aValue)) \ 258 BIND_GEN_IMPL(_class, _optionalGuard, Int32, \ 259 (const nsACString& aWhere, int32_t aValue), \ 260 (uint32_t aWhere, int32_t aValue), (aWhere, aValue)) \ 261 BIND_GEN_IMPL(_class, _optionalGuard, Int64, \ 262 (const nsACString& aWhere, int64_t aValue), \ 263 (uint32_t aWhere, int64_t aValue), (aWhere, aValue)) \ 264 BIND_GEN_IMPL(_class, _optionalGuard, Null, (const nsACString& aWhere), \ 265 (uint32_t aWhere), (aWhere)) \ 266 BIND_GEN_IMPL( \ 267 _class, _optionalGuard, Blob, \ 268 (const nsACString& aWhere, const uint8_t* aValue, uint32_t aValueSize), \ 269 (uint32_t aWhere, const uint8_t* aValue, uint32_t aValueSize), \ 270 (aWhere, aValue, aValueSize)) \ 271 BIND_GEN_IMPL(_class, _optionalGuard, BlobArray, \ 272 (const nsACString& aWhere, const nsTArray<uint8_t>& aValue), \ 273 (uint32_t aWhere, const nsTArray<uint8_t>& aValue), \ 274 (aWhere, aValue)) \ 275 BIND_GEN_IMPL(_class, _optionalGuard, StringAsBlob, \ 276 (const nsACString& aWhere, const nsAString& aValue), \ 277 (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue)) \ 278 BIND_GEN_IMPL(_class, _optionalGuard, UTF8StringAsBlob, \ 279 (const nsACString& aWhere, const nsACString& aValue), \ 280 (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \ 281 BIND_GEN_IMPL( \ 282 _class, _optionalGuard, AdoptedBlob, \ 283 (const nsACString& aWhere, uint8_t* aValue, uint32_t aValueSize), \ 284 (uint32_t aWhere, uint8_t* aValue, uint32_t aValueSize), \ 285 (aWhere, aValue, aValueSize)) \ 286 BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfIntegers, \ 287 (const nsACString& aWhere, const nsTArray<int64_t>& aValue), \ 288 (uint32_t aWhere, const nsTArray<int64_t>& aValue), \ 289 (aWhere, aValue)) \ 290 BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfDoubles, \ 291 (const nsACString& aWhere, const nsTArray<double>& aValue), \ 292 (uint32_t aWhere, const nsTArray<double>& aValue), \ 293 (aWhere, aValue)) \ 294 BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfStrings, \ 295 (const nsACString& aWhere, const nsTArray<nsString>& aValue), \ 296 (uint32_t aWhere, const nsTArray<nsString>& aValue), \ 297 (aWhere, aValue)) \ 298 BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfUTF8Strings, \ 299 (const nsACString& aWhere, const nsTArray<nsCString>& aValue), \ 300 (uint32_t aWhere, const nsTArray<nsCString>& aValue), \ 301 (aWhere, aValue)) 302 303 } // namespace storage 304 } // namespace mozilla 305 306 #endif // mozilla_storage_StorageBaseStatementInternal_h_