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