storage/src/StorageBaseStatementInternal.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:a252bb144cde
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_

mercurial