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