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 "nsAutoPtr.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 { 44 public: NS_DECLARE_STATIC_IID_ACCESSOR(STORAGEBASESTATEMENTINTERNAL_IID)45 NS_DECLARE_STATIC_IID_ACCESSOR(STORAGEBASESTATEMENTINTERNAL_IID) 46 47 /** 48 * @return the connection that this statement belongs to. 49 */ 50 Connection *getOwner() 51 { 52 return mDBConnection; 53 } 54 55 /** 56 * Return the asynchronous statement, creating it if required. 57 * 58 * This is for use by the asynchronous execution code for StatementData 59 * created by AsyncStatements. Statement internally uses this method to 60 * prepopulate StatementData with the sqlite3_stmt. 61 * 62 * @param[out] stmt 63 * The sqlite3_stmt for asynchronous use. 64 * @return The SQLite result code for creating the statement if created, 65 * SQLITE_OK if creation was not required. 66 */ 67 virtual int getAsyncStatement(sqlite3_stmt **_stmt) = 0; 68 69 /** 70 * Obtains the StatementData needed for asynchronous execution. 71 * 72 * This is for use by Connection to retrieve StatementData from statements 73 * when executeAsync is invoked. 74 * 75 * @param[out] _data 76 * A reference to a StatementData object that will be populated 77 * upon successful execution of this method. 78 * @return NS_OK if we were able to assemble the data, failure otherwise. 79 */ 80 virtual nsresult getAsynchronousStatementData(StatementData &_data) = 0; 81 82 /** 83 * Construct a new BindingParams to be owned by the provided binding params 84 * array. This method exists so that BindingParamsArray does not need 85 * factory logic to determine what type of BindingParams to instantiate. 86 * 87 * @param aOwner 88 * The binding params array to own the newly created binding params. 89 * @return The new mozIStorageBindingParams instance appropriate to the 90 * underlying statement type. 91 */ 92 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( 93 mozIStorageBindingParamsArray *aOwner 94 ) = 0; 95 96 protected: // mix-in bits are protected 97 StorageBaseStatementInternal(); 98 99 RefPtr<Connection> mDBConnection; 100 sqlite3 *mNativeConnection; 101 102 /** 103 * Our asynchronous statement. 104 * 105 * For Statement this is populated by the first invocation to 106 * getAsyncStatement. 107 * 108 * For AsyncStatement, this is null at creation time and initialized by the 109 * async thread when it calls getAsyncStatement the first time the statement 110 * is executed. (Or in the event of badly formed SQL, every time.) 111 */ 112 sqlite3_stmt *mAsyncStatement; 113 114 /** 115 * Initiate asynchronous finalization by dispatching an event to the 116 * asynchronous thread to finalize mAsyncStatement. This acquires a reference 117 * to this statement and proxies it back to the connection's owning thread 118 * for release purposes. 119 * 120 * In the event the asynchronous thread is already gone or we otherwise fail 121 * to dispatch an event to it we failover to invoking internalAsyncFinalize 122 * directly. (That's what the asynchronous finalizer would have called.) 123 * 124 * @note You must not call this method from your destructor because its 125 * operation assumes we are still alive. Call internalAsyncFinalize 126 * directly in that case. 127 */ 128 void asyncFinalize(); 129 130 /** 131 * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists by 132 * attempting to dispatch to the asynchronous thread if available, finalizing 133 * on this thread if it is not. 134 * 135 * @note Call this from your destructor, call asyncFinalize otherwise. 136 */ 137 void destructorAsyncFinalize(); 138 139 NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray **_array); 140 NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback *aCallback, 141 mozIStoragePendingStatement **_stmt); 142 NS_IMETHOD EscapeStringForLIKE(const nsAString &aValue, 143 char16_t aEscapeChar, 144 nsAString &_escapedString); 145 146 // Needs access to internalAsyncFinalize 147 friend class AsyncStatementFinalizer; 148 }; 149 150 NS_DEFINE_STATIC_IID_ACCESSOR(StorageBaseStatementInternal, 151 STORAGEBASESTATEMENTINTERNAL_IID) 152 153 #define NS_DECL_STORAGEBASESTATEMENTINTERNAL \ 154 virtual Connection *getOwner(); \ 155 virtual int getAsyncStatement(sqlite3_stmt **_stmt) override; \ 156 virtual nsresult getAsynchronousStatementData(StatementData &_data) override; \ 157 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \ 158 mozIStorageBindingParamsArray *aOwner) override; 159 160 /** 161 * Helper macro to implement the proxying implementations. Because we are 162 * implementing methods that are part of mozIStorageBaseStatement and the 163 * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't 164 * need to provide declaration support. 165 */ 166 #define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs) \ 167 NS_IMETHODIMP _class::_method _declArgs \ 168 { \ 169 _optionalGuard \ 170 return StorageBaseStatementInternal::_method _invokeArgs; \ 171 } 172 173 174 /** 175 * Define proxying implementation for the given _class. If a state invariant 176 * needs to be checked and an early return possibly performed, pass the clause 177 * to use as _optionalGuard. 178 */ 179 #define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \ 180 MIX_IMPL(_class, _optionalGuard, \ 181 NewBindingParamsArray, \ 182 (mozIStorageBindingParamsArray **_array), \ 183 (_array)) \ 184 MIX_IMPL(_class, _optionalGuard, \ 185 ExecuteAsync, \ 186 (mozIStorageStatementCallback *aCallback, \ 187 mozIStoragePendingStatement **_stmt), \ 188 (aCallback, _stmt)) \ 189 MIX_IMPL(_class, _optionalGuard, \ 190 EscapeStringForLIKE, \ 191 (const nsAString &aValue, char16_t aEscapeChar, \ 192 nsAString &_escapedString), \ 193 (aValue, aEscapeChar, _escapedString)) 194 195 /** 196 * Name-building helper for BIND_GEN_IMPL. 197 */ 198 #define BIND_NAME_CONCAT(_nameBit, _concatBit) \ 199 Bind##_nameBit##_concatBit 200 201 /** 202 * We have type-specific convenience methods for C++ implementations in 203 * 3 different forms; 2 by index, 1 by name. The following macro allows 204 * us to avoid having to define repetitive things by hand. 205 * 206 * Because of limitations of macros and our desire to avoid requiring special 207 * permutations for the null and blob cases (whose argument count varies), 208 * we require that the argument declarations and corresponding invocation 209 * usages are passed in. 210 * 211 * @param _class 212 * The class name. 213 * @param _guard 214 * The guard clause to inject. 215 * @param _declName 216 * The argument list (with parens) for the ByName variants. 217 * @param _declIndex 218 * The argument list (with parens) for the index variants. 219 * @param _invArgs 220 * The invocation argumment list. 221 */ 222 #define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \ 223 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName \ 224 { \ 225 _guard \ 226 mozIStorageBindingParams *params = getParams(); \ 227 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 228 return params->BIND_NAME_CONCAT(_name, ByName) _invArgs; \ 229 } \ 230 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex \ 231 { \ 232 _guard \ 233 mozIStorageBindingParams *params = getParams(); \ 234 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 235 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \ 236 } \ 237 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, Parameter) _declIndex \ 238 { \ 239 _guard \ 240 mozIStorageBindingParams *params = getParams(); \ 241 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 242 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \ 243 } 244 245 /** 246 * Implement BindByName/BindByIndex for the given class. 247 * 248 * @param _class The class name. 249 * @param _optionalGuard The guard clause to inject. 250 */ 251 #define BIND_BASE_IMPLS(_class, _optionalGuard) \ 252 NS_IMETHODIMP _class::BindByName(const nsACString &aName, \ 253 nsIVariant *aValue) \ 254 { \ 255 _optionalGuard \ 256 mozIStorageBindingParams *params = getParams(); \ 257 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 258 return params->BindByName(aName, aValue); \ 259 } \ 260 NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, \ 261 nsIVariant *aValue) \ 262 { \ 263 _optionalGuard \ 264 mozIStorageBindingParams *params = getParams(); \ 265 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ 266 return params->BindByIndex(aIndex, aValue); \ 267 } 268 269 /** 270 * Define the various Bind*Parameter, Bind*ByIndex, Bind*ByName stubs that just 271 * end up proxying to the params object. 272 */ 273 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \ 274 BIND_BASE_IMPLS(_class, _optionalGuard) \ 275 BIND_GEN_IMPL(_class, _optionalGuard, \ 276 UTF8String, \ 277 (const nsACString &aWhere, \ 278 const nsACString &aValue), \ 279 (uint32_t aWhere, \ 280 const nsACString &aValue), \ 281 (aWhere, aValue)) \ 282 BIND_GEN_IMPL(_class, _optionalGuard, \ 283 String, \ 284 (const nsACString &aWhere, \ 285 const nsAString &aValue), \ 286 (uint32_t aWhere, \ 287 const nsAString &aValue), \ 288 (aWhere, aValue)) \ 289 BIND_GEN_IMPL(_class, _optionalGuard, \ 290 Double, \ 291 (const nsACString &aWhere, \ 292 double aValue), \ 293 (uint32_t aWhere, \ 294 double aValue), \ 295 (aWhere, aValue)) \ 296 BIND_GEN_IMPL(_class, _optionalGuard, \ 297 Int32, \ 298 (const nsACString &aWhere, \ 299 int32_t aValue), \ 300 (uint32_t aWhere, \ 301 int32_t aValue), \ 302 (aWhere, aValue)) \ 303 BIND_GEN_IMPL(_class, _optionalGuard, \ 304 Int64, \ 305 (const nsACString &aWhere, \ 306 int64_t aValue), \ 307 (uint32_t aWhere, \ 308 int64_t aValue), \ 309 (aWhere, aValue)) \ 310 BIND_GEN_IMPL(_class, _optionalGuard, \ 311 Null, \ 312 (const nsACString &aWhere), \ 313 (uint32_t aWhere), \ 314 (aWhere)) \ 315 BIND_GEN_IMPL(_class, _optionalGuard, \ 316 Blob, \ 317 (const nsACString &aWhere, \ 318 const uint8_t *aValue, \ 319 uint32_t aValueSize), \ 320 (uint32_t aWhere, \ 321 const uint8_t *aValue, \ 322 uint32_t aValueSize), \ 323 (aWhere, aValue, aValueSize)) \ 324 BIND_GEN_IMPL(_class, _optionalGuard, \ 325 StringAsBlob, \ 326 (const nsACString &aWhere, \ 327 const nsAString& aValue), \ 328 (uint32_t aWhere, \ 329 const nsAString& aValue), \ 330 (aWhere, aValue)) \ 331 BIND_GEN_IMPL(_class, _optionalGuard, \ 332 UTF8StringAsBlob, \ 333 (const nsACString &aWhere, \ 334 const nsACString& aValue), \ 335 (uint32_t aWhere, \ 336 const nsACString& aValue), \ 337 (aWhere, aValue)) \ 338 BIND_GEN_IMPL(_class, _optionalGuard, \ 339 AdoptedBlob, \ 340 (const nsACString &aWhere, \ 341 uint8_t *aValue, \ 342 uint32_t aValueSize), \ 343 (uint32_t aWhere, \ 344 uint8_t *aValue, \ 345 uint32_t aValueSize), \ 346 (aWhere, aValue, aValueSize)) 347 348 349 350 } // namespace storage 351 } // namespace mozilla 352 353 #endif // mozilla_storage_StorageBaseStatementInternal_h_ 354