Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / storage / StorageBaseStatementInternal.h
blob685f0f79d0004228e03012ee9476b2f757dc4d14
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/. */
7 #ifndef mozilla_storage_StorageBaseStatementInternal_h_
8 #define mozilla_storage_StorageBaseStatementInternal_h_
10 #include "nsISupports.h"
11 #include "nsCOMPtr.h"
12 #include "mozStorageHelper.h"
14 struct sqlite3;
15 struct sqlite3_stmt;
16 class mozIStorageBindingParamsArray;
17 class mozIStorageBindingParams;
18 class mozIStorageStatementCallback;
19 class mozIStoragePendingStatement;
21 namespace mozilla {
22 namespace storage {
24 #define STORAGEBASESTATEMENTINTERNAL_IID \
25 { \
26 0xd18856c9, 0xbf07, 0x4ae2, { \
27 0x94, 0x5b, 0x1a, 0xdd, 0x49, 0x19, 0x55, 0x2a \
28 } \
31 class Connection;
32 class StatementData;
34 class AsyncStatementFinalizer;
36 /**
37 * Implementation-only interface and shared logix mix-in corresponding to
38 * mozIStorageBaseStatement. Both Statement and AsyncStatement inherit from
39 * this. The interface aspect makes them look the same to implementation innards
40 * that aren't publicly accessible. The mix-in avoids code duplication in
41 * common implementations of mozIStorageBaseStatement, albeit with some minor
42 * performance/space overhead because we have to use defines to officially
43 * implement the methods on Statement/AsyncStatement (and proxy to this base
44 * class.)
46 class StorageBaseStatementInternal : public nsISupports {
47 public:
48 NS_DECLARE_STATIC_IID_ACCESSOR(STORAGEBASESTATEMENTINTERNAL_IID)
50 /**
51 * @return the connection that this statement belongs to.
53 Connection* getOwner() { return mDBConnection; }
55 /**
56 * Return the asynchronous statement, creating it if required.
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.
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.
67 virtual int getAsyncStatement(sqlite3_stmt** _stmt) = 0;
69 /**
70 * Obtains the StatementData needed for asynchronous execution.
72 * This is for use by Connection to retrieve StatementData from statements
73 * when executeAsync is invoked.
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.
80 virtual nsresult getAsynchronousStatementData(StatementData& _data) = 0;
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.
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.
92 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams(
93 mozIStorageBindingParamsArray* aOwner) = 0;
95 protected: // mix-in bits are protected
96 StorageBaseStatementInternal();
98 RefPtr<Connection> mDBConnection;
99 sqlite3* mNativeConnection;
102 * Our asynchronous statement.
104 * For Statement this is populated by the first invocation to
105 * getAsyncStatement.
107 * For AsyncStatement, this is null at creation time and initialized by the
108 * async thread when it calls getAsyncStatement the first time the statement
109 * is executed. (Or in the event of badly formed SQL, every time.)
111 sqlite3_stmt* mAsyncStatement;
114 * Initiate asynchronous finalization by dispatching an event to the
115 * asynchronous thread to finalize mAsyncStatement. This acquires a reference
116 * to this statement and proxies it back to the connection's owning thread
117 * for release purposes.
119 * In the event the asynchronous thread is already gone or we otherwise fail
120 * to dispatch an event to it we failover to invoking internalAsyncFinalize
121 * directly. (That's what the asynchronous finalizer would have called.)
123 * @note You must not call this method from your destructor because its
124 * operation assumes we are still alive. Call internalAsyncFinalize
125 * directly in that case.
127 void asyncFinalize();
130 * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists by
131 * attempting to dispatch to the asynchronous thread if available, finalizing
132 * on this thread if it is not.
134 * @note Call this from your destructor, call asyncFinalize otherwise.
136 void destructorAsyncFinalize();
138 NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray** _array);
139 NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback* aCallback,
140 mozIStoragePendingStatement** _stmt);
141 NS_IMETHOD EscapeStringForLIKE(const nsAString& aValue, char16_t aEscapeChar,
142 nsAString& _escapedString);
143 NS_IMETHOD EscapeUTF8StringForLIKE(const nsACString& aValue, char aEscapeChar,
144 nsACString& _escapedString);
146 // Needs access to internalAsyncFinalize
147 friend class AsyncStatementFinalizer;
150 NS_DEFINE_STATIC_IID_ACCESSOR(StorageBaseStatementInternal,
151 STORAGEBASESTATEMENTINTERNAL_IID)
153 #define NS_DECL_STORAGEBASESTATEMENTINTERNAL \
154 virtual Connection* getOwner(); \
155 virtual int getAsyncStatement(sqlite3_stmt** _stmt) override; \
156 virtual nsresult getAsynchronousStatementData(StatementData& _data) \
157 override; \
158 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \
159 mozIStorageBindingParamsArray* aOwner) override;
162 * Helper macro to implement the proxying implementations. Because we are
163 * implementing methods that are part of mozIStorageBaseStatement and the
164 * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't
165 * need to provide declaration support.
167 #define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs) \
168 NS_IMETHODIMP _class::_method _declArgs { \
169 _optionalGuard return StorageBaseStatementInternal::_method _invokeArgs; \
173 * Define proxying implementation for the given _class. If a state invariant
174 * needs to be checked and an early return possibly performed, pass the clause
175 * to use as _optionalGuard.
177 #define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \
178 MIX_IMPL(_class, _optionalGuard, NewBindingParamsArray, \
179 (mozIStorageBindingParamsArray * *_array), (_array)) \
180 MIX_IMPL(_class, _optionalGuard, ExecuteAsync, \
181 (mozIStorageStatementCallback * aCallback, \
182 mozIStoragePendingStatement * *_stmt), \
183 (aCallback, _stmt)) \
184 MIX_IMPL(_class, _optionalGuard, EscapeStringForLIKE, \
185 (const nsAString& aValue, char16_t aEscapeChar, \
186 nsAString& _escapedString), \
187 (aValue, aEscapeChar, _escapedString)) \
188 MIX_IMPL(_class, _optionalGuard, EscapeUTF8StringForLIKE, \
189 (const nsACString& aValue, char aEscapeChar, \
190 nsACString& _escapedString), \
191 (aValue, aEscapeChar, _escapedString))
194 * Name-building helper for BIND_GEN_IMPL.
196 #define BIND_NAME_CONCAT(_nameBit, _concatBit) Bind##_nameBit##_concatBit
199 * We have type-specific convenience methods for C++ implementations in
200 * two different forms; by index and by name. The following macro allows
201 * us to avoid having to define repetitive things by hand.
203 * Because of limitations of macros and our desire to avoid requiring special
204 * permutations for the null and blob cases (whose argument count varies),
205 * we require that the argument declarations and corresponding invocation
206 * usages are passed in.
208 * @param _class
209 * The class name.
210 * @param _guard
211 * The guard clause to inject.
212 * @param _declName
213 * The argument list (with parens) for the ByName variants.
214 * @param _declIndex
215 * The argument list (with parens) for the ByIndex variants.
216 * @param _invArgs
217 * The invocation argumment list.
219 #define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \
220 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName { \
221 _guard mozIStorageBindingParams* params = getParams(); \
222 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
223 return params->BIND_NAME_CONCAT(_name, ByName) _invArgs; \
225 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex { \
226 _guard mozIStorageBindingParams* params = getParams(); \
227 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
228 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \
232 * Implement BindByName/BindByIndex for the given class.
234 * @param _class The class name.
235 * @param _optionalGuard The guard clause to inject.
237 #define BIND_BASE_IMPLS(_class, _optionalGuard) \
238 NS_IMETHODIMP _class::BindByName(const nsACString& aName, \
239 nsIVariant* aValue) { \
240 _optionalGuard mozIStorageBindingParams* params = getParams(); \
241 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
242 return params->BindByName(aName, aValue); \
244 NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, nsIVariant* aValue) { \
245 _optionalGuard mozIStorageBindingParams* params = getParams(); \
246 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
247 return params->BindByIndex(aIndex, aValue); \
251 * Define the various Bind*ByIndex, Bind*ByName stubs that just end up proxying
252 * to the params object.
254 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \
255 BIND_BASE_IMPLS(_class, _optionalGuard) \
256 BIND_GEN_IMPL(_class, _optionalGuard, UTF8String, \
257 (const nsACString& aWhere, const nsACString& aValue), \
258 (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \
259 BIND_GEN_IMPL(_class, _optionalGuard, String, \
260 (const nsACString& aWhere, const nsAString& aValue), \
261 (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue)) \
262 BIND_GEN_IMPL(_class, _optionalGuard, Double, \
263 (const nsACString& aWhere, double aValue), \
264 (uint32_t aWhere, double aValue), (aWhere, aValue)) \
265 BIND_GEN_IMPL(_class, _optionalGuard, Int32, \
266 (const nsACString& aWhere, int32_t aValue), \
267 (uint32_t aWhere, int32_t aValue), (aWhere, aValue)) \
268 BIND_GEN_IMPL(_class, _optionalGuard, Int64, \
269 (const nsACString& aWhere, int64_t aValue), \
270 (uint32_t aWhere, int64_t aValue), (aWhere, aValue)) \
271 BIND_GEN_IMPL(_class, _optionalGuard, Null, (const nsACString& aWhere), \
272 (uint32_t aWhere), (aWhere)) \
273 BIND_GEN_IMPL( \
274 _class, _optionalGuard, Blob, \
275 (const nsACString& aWhere, const uint8_t* aValue, uint32_t aValueSize), \
276 (uint32_t aWhere, const uint8_t* aValue, uint32_t aValueSize), \
277 (aWhere, aValue, aValueSize)) \
278 BIND_GEN_IMPL(_class, _optionalGuard, BlobArray, \
279 (const nsACString& aWhere, const nsTArray<uint8_t>& aValue), \
280 (uint32_t aWhere, const nsTArray<uint8_t>& aValue), \
281 (aWhere, aValue)) \
282 BIND_GEN_IMPL(_class, _optionalGuard, StringAsBlob, \
283 (const nsACString& aWhere, const nsAString& aValue), \
284 (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue)) \
285 BIND_GEN_IMPL(_class, _optionalGuard, UTF8StringAsBlob, \
286 (const nsACString& aWhere, const nsACString& aValue), \
287 (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \
288 BIND_GEN_IMPL( \
289 _class, _optionalGuard, AdoptedBlob, \
290 (const nsACString& aWhere, uint8_t* aValue, uint32_t aValueSize), \
291 (uint32_t aWhere, uint8_t * aValue, uint32_t aValueSize), \
292 (aWhere, aValue, aValueSize))
294 } // namespace storage
295 } // namespace mozilla
297 #endif // mozilla_storage_StorageBaseStatementInternal_h_