|
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 mozIStorageError; |
|
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 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 Connection *getOwner() |
|
52 { |
|
53 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 nsRefPtr<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 const 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); \ |
|
157 virtual nsresult getAsynchronousStatementData(StatementData &_data); \ |
|
158 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \ |
|
159 mozIStorageBindingParamsArray *aOwner); |
|
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, const 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 _guard \ |
|
241 mozIStorageBindingParams *params = getParams(); \ |
|
242 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ |
|
243 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \ |
|
244 } |
|
245 |
|
246 /** |
|
247 * Implement BindByName/BindByIndex for the given class. |
|
248 * |
|
249 * @param _class The class name. |
|
250 * @param _optionalGuard The guard clause to inject. |
|
251 */ |
|
252 #define BIND_BASE_IMPLS(_class, _optionalGuard) \ |
|
253 NS_IMETHODIMP _class::BindByName(const nsACString &aName, \ |
|
254 nsIVariant *aValue) \ |
|
255 { \ |
|
256 _optionalGuard \ |
|
257 mozIStorageBindingParams *params = getParams(); \ |
|
258 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ |
|
259 return params->BindByName(aName, aValue); \ |
|
260 } \ |
|
261 NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, \ |
|
262 nsIVariant *aValue) \ |
|
263 { \ |
|
264 _optionalGuard \ |
|
265 mozIStorageBindingParams *params = getParams(); \ |
|
266 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \ |
|
267 return params->BindByIndex(aIndex, aValue); \ |
|
268 } |
|
269 |
|
270 /** |
|
271 * Define the various Bind*Parameter, Bind*ByIndex, Bind*ByName stubs that just |
|
272 * end up proxying to the params object. |
|
273 */ |
|
274 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \ |
|
275 BIND_BASE_IMPLS(_class, _optionalGuard) \ |
|
276 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
277 UTF8String, \ |
|
278 (const nsACString &aWhere, \ |
|
279 const nsACString &aValue), \ |
|
280 (uint32_t aWhere, \ |
|
281 const nsACString &aValue), \ |
|
282 (aWhere, aValue)) \ |
|
283 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
284 String, \ |
|
285 (const nsACString &aWhere, \ |
|
286 const nsAString &aValue), \ |
|
287 (uint32_t aWhere, \ |
|
288 const nsAString &aValue), \ |
|
289 (aWhere, aValue)) \ |
|
290 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
291 Double, \ |
|
292 (const nsACString &aWhere, \ |
|
293 double aValue), \ |
|
294 (uint32_t aWhere, \ |
|
295 double aValue), \ |
|
296 (aWhere, aValue)) \ |
|
297 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
298 Int32, \ |
|
299 (const nsACString &aWhere, \ |
|
300 int32_t aValue), \ |
|
301 (uint32_t aWhere, \ |
|
302 int32_t aValue), \ |
|
303 (aWhere, aValue)) \ |
|
304 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
305 Int64, \ |
|
306 (const nsACString &aWhere, \ |
|
307 int64_t aValue), \ |
|
308 (uint32_t aWhere, \ |
|
309 int64_t aValue), \ |
|
310 (aWhere, aValue)) \ |
|
311 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
312 Null, \ |
|
313 (const nsACString &aWhere), \ |
|
314 (uint32_t aWhere), \ |
|
315 (aWhere)) \ |
|
316 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
317 Blob, \ |
|
318 (const nsACString &aWhere, \ |
|
319 const uint8_t *aValue, \ |
|
320 uint32_t aValueSize), \ |
|
321 (uint32_t aWhere, \ |
|
322 const uint8_t *aValue, \ |
|
323 uint32_t aValueSize), \ |
|
324 (aWhere, aValue, aValueSize)) \ |
|
325 BIND_GEN_IMPL(_class, _optionalGuard, \ |
|
326 AdoptedBlob, \ |
|
327 (const nsACString &aWhere, \ |
|
328 uint8_t *aValue, \ |
|
329 uint32_t aValueSize), \ |
|
330 (uint32_t aWhere, \ |
|
331 uint8_t *aValue, \ |
|
332 uint32_t aValueSize), \ |
|
333 (aWhere, aValue, aValueSize)) |
|
334 |
|
335 |
|
336 |
|
337 } // storage |
|
338 } // mozilla |
|
339 |
|
340 #endif // mozilla_storage_StorageBaseStatementInternal_h_ |