Bug 628949 - Update visible region / glass regions after we paint. r=roc a=2.0.
[mozilla-central.git] / storage / src / mozStorageBindingParams.cpp
blobd99075b02669de44b692cf9333cfa4a24f64bbf8
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Mozilla Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Shawn Wilsher <me@shawnwilsher.com> (Original Author)
25 * Andrew Sutherland <asutherland@asutherland.org>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include <limits.h>
43 #include "nsString.h"
45 #include "mozStorageError.h"
46 #include "mozStoragePrivateHelpers.h"
47 #include "mozStorageBindingParams.h"
48 #include "mozStorageBindingParamsArray.h"
49 #include "Variant.h"
51 namespace mozilla {
52 namespace storage {
54 ////////////////////////////////////////////////////////////////////////////////
55 //// Local Helper Objects
57 namespace {
59 struct BindingColumnData
61 BindingColumnData(sqlite3_stmt *aStmt,
62 int aColumn)
63 : stmt(aStmt)
64 , column(aColumn)
67 sqlite3_stmt *stmt;
68 int column;
71 ////////////////////////////////////////////////////////////////////////////////
72 //// Variant Specialization Functions (variantToSQLiteT)
74 int
75 sqlite3_T_int(BindingColumnData aData,
76 int aValue)
78 return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
81 int
82 sqlite3_T_int64(BindingColumnData aData,
83 sqlite3_int64 aValue)
85 return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
88 int
89 sqlite3_T_double(BindingColumnData aData,
90 double aValue)
92 return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
95 int
96 sqlite3_T_text(BindingColumnData aData,
97 const nsCString& aValue)
99 return ::sqlite3_bind_text(aData.stmt,
100 aData.column + 1,
101 aValue.get(),
102 aValue.Length(),
103 SQLITE_TRANSIENT);
107 sqlite3_T_text16(BindingColumnData aData,
108 const nsString& aValue)
110 return ::sqlite3_bind_text16(aData.stmt,
111 aData.column + 1,
112 aValue.get(),
113 aValue.Length() * 2, // Length in bytes!
114 SQLITE_TRANSIENT);
118 sqlite3_T_null(BindingColumnData aData)
120 return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
124 sqlite3_T_blob(BindingColumnData aData,
125 const void *aBlob,
126 int aSize)
128 return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
129 NS_Free);
133 #include "variantToSQLiteT_impl.h"
135 } // anonymous namespace
137 ////////////////////////////////////////////////////////////////////////////////
138 //// BindingParams
140 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
141 Statement *aOwningStatement)
142 : mLocked(false)
143 , mOwningArray(aOwningArray)
144 , mOwningStatement(aOwningStatement)
146 (void)mOwningStatement->GetParameterCount(&mParamCount);
147 (void)mParameters.SetCapacity(mParamCount);
150 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
151 : mLocked(false)
152 , mOwningArray(aOwningArray)
153 , mOwningStatement(nsnull)
154 , mParamCount(0)
158 AsyncBindingParams::AsyncBindingParams(
159 mozIStorageBindingParamsArray *aOwningArray
161 : BindingParams(aOwningArray)
163 mNamedParameters.Init();
166 void
167 BindingParams::lock()
169 NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
170 mLocked = true;
172 // We no longer need to hold a reference to our statement or our owning array.
173 // The array owns us at this point, and it will own a reference to the
174 // statement.
175 mOwningStatement = nsnull;
176 mOwningArray = nsnull;
179 void
180 BindingParams::unlock(Statement *aOwningStatement)
182 NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
183 mLocked = false;
184 mOwningStatement = aOwningStatement;
187 const mozIStorageBindingParamsArray *
188 BindingParams::getOwner() const
190 return mOwningArray;
193 PLDHashOperator
194 AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
195 nsIVariant *aValue,
196 void *voidClosureThunk)
198 NamedParameterIterationClosureThunk *closureThunk =
199 static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
201 // We do not accept any forms of names other than ":name", but we need to add
202 // the colon for SQLite.
203 nsCAutoString name(":");
204 name.Append(aName);
205 int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
206 name.get());
208 if (oneIdx == 0) {
209 nsCAutoString errMsg(aName);
210 errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
211 closureThunk->err = new Error(SQLITE_RANGE, errMsg.get());
212 return PL_DHASH_STOP;
215 // XPCVariant's AddRef and Release are not thread-safe and so we must not do
216 // anything that would invoke them here on the async thread. As such we can't
217 // cram aValue into self->mParameters using ReplaceObjectAt so that we can
218 // freeload off of the BindingParams::Bind implementation.
219 int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement,
220 oneIdx - 1),
221 aValue);
222 if (rc != SQLITE_OK) {
223 // We had an error while trying to bind. Now we need to create an error
224 // object with the right message. Note that we special case
225 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
226 const char *msg = "Could not covert nsIVariant to SQLite type.";
227 if (rc != SQLITE_MISMATCH)
228 msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
230 closureThunk->err = new Error(rc, msg);
231 return PL_DHASH_STOP;
233 return PL_DHASH_NEXT;
236 ////////////////////////////////////////////////////////////////////////////////
237 //// nsISupports
239 NS_IMPL_THREADSAFE_ISUPPORTS2(
240 BindingParams
241 , mozIStorageBindingParams
242 , IStorageBindingParamsInternal
246 ////////////////////////////////////////////////////////////////////////////////
247 //// IStorageBindingParamsInternal
249 already_AddRefed<mozIStorageError>
250 BindingParams::bind(sqlite3_stmt *aStatement)
252 // Iterate through all of our stored data, and bind it.
253 for (PRInt32 i = 0; i < mParameters.Count(); i++) {
254 int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
255 if (rc != SQLITE_OK) {
256 // We had an error while trying to bind. Now we need to create an error
257 // object with the right message. Note that we special case
258 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
259 const char *msg = "Could not covert nsIVariant to SQLite type.";
260 if (rc != SQLITE_MISMATCH)
261 msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
263 nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
264 return err.forget();
268 return nsnull;
271 already_AddRefed<mozIStorageError>
272 AsyncBindingParams::bind(sqlite3_stmt * aStatement)
274 // We should bind by index using the super-class if there is nothing in our
275 // hashtable.
276 if (!mNamedParameters.Count())
277 return BindingParams::bind(aStatement);
279 // Enumerate over everyone in the map, propagating them into mParameters if
280 // we can and creating an error immediately when we cannot.
281 NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nsnull};
282 (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
283 (void *)&closureThunk);
285 return closureThunk.err.forget();
289 ///////////////////////////////////////////////////////////////////////////////
290 //// mozIStorageBindingParams
292 NS_IMETHODIMP
293 BindingParams::BindByName(const nsACString &aName,
294 nsIVariant *aValue)
296 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
298 // Get the column index that we need to store this at.
299 PRUint32 index;
300 nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
301 NS_ENSURE_SUCCESS(rv, rv);
303 return BindByIndex(index, aValue);
306 NS_IMETHODIMP
307 AsyncBindingParams::BindByName(const nsACString &aName,
308 nsIVariant *aValue)
310 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
312 if (!mNamedParameters.Put(aName, aValue))
313 return NS_ERROR_OUT_OF_MEMORY;
314 return NS_OK;
318 NS_IMETHODIMP
319 BindingParams::BindUTF8StringByName(const nsACString &aName,
320 const nsACString &aValue)
322 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
323 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
325 return BindByName(aName, value);
328 NS_IMETHODIMP
329 BindingParams::BindStringByName(const nsACString &aName,
330 const nsAString &aValue)
332 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
333 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
335 return BindByName(aName, value);
338 NS_IMETHODIMP
339 BindingParams::BindDoubleByName(const nsACString &aName,
340 double aValue)
342 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
343 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
345 return BindByName(aName, value);
348 NS_IMETHODIMP
349 BindingParams::BindInt32ByName(const nsACString &aName,
350 PRInt32 aValue)
352 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
353 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
355 return BindByName(aName, value);
358 NS_IMETHODIMP
359 BindingParams::BindInt64ByName(const nsACString &aName,
360 PRInt64 aValue)
362 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
363 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
365 return BindByName(aName, value);
368 NS_IMETHODIMP
369 BindingParams::BindNullByName(const nsACString &aName)
371 nsCOMPtr<nsIVariant> value(new NullVariant());
372 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
374 return BindByName(aName, value);
377 NS_IMETHODIMP
378 BindingParams::BindBlobByName(const nsACString &aName,
379 const PRUint8 *aValue,
380 PRUint32 aValueSize)
382 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
383 std::pair<const void *, int> data(
384 static_cast<const void *>(aValue),
385 int(aValueSize)
387 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
388 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
390 return BindByName(aName, value);
393 NS_IMETHODIMP
394 BindingParams::BindByIndex(PRUint32 aIndex,
395 nsIVariant *aValue)
397 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
398 ENSURE_INDEX_VALUE(aIndex, mParamCount);
400 // Store the variant for later use.
401 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
402 NS_ERROR_OUT_OF_MEMORY);
403 return NS_OK;
406 NS_IMETHODIMP
407 AsyncBindingParams::BindByIndex(PRUint32 aIndex,
408 nsIVariant *aValue)
410 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
411 // In the asynchronous case we do not know how many parameters there are to
412 // bind to, so we cannot check the validity of aIndex.
414 // Store the variant for later use.
415 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
416 NS_ERROR_OUT_OF_MEMORY);
417 return NS_OK;
420 NS_IMETHODIMP
421 BindingParams::BindUTF8StringByIndex(PRUint32 aIndex,
422 const nsACString &aValue)
424 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
425 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
427 return BindByIndex(aIndex, value);
430 NS_IMETHODIMP
431 BindingParams::BindStringByIndex(PRUint32 aIndex,
432 const nsAString &aValue)
434 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
435 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
437 return BindByIndex(aIndex, value);
440 NS_IMETHODIMP
441 BindingParams::BindDoubleByIndex(PRUint32 aIndex,
442 double aValue)
444 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
445 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
447 return BindByIndex(aIndex, value);
450 NS_IMETHODIMP
451 BindingParams::BindInt32ByIndex(PRUint32 aIndex,
452 PRInt32 aValue)
454 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
455 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
457 return BindByIndex(aIndex, value);
460 NS_IMETHODIMP
461 BindingParams::BindInt64ByIndex(PRUint32 aIndex,
462 PRInt64 aValue)
464 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
465 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
467 return BindByIndex(aIndex, value);
470 NS_IMETHODIMP
471 BindingParams::BindNullByIndex(PRUint32 aIndex)
473 nsCOMPtr<nsIVariant> value(new NullVariant());
474 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
476 return BindByIndex(aIndex, value);
479 NS_IMETHODIMP
480 BindingParams::BindBlobByIndex(PRUint32 aIndex,
481 const PRUint8 *aValue,
482 PRUint32 aValueSize)
484 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
485 std::pair<const void *, int> data(
486 static_cast<const void *>(aValue),
487 int(aValueSize)
489 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
490 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
492 return BindByIndex(aIndex, value);
495 } // namespace storage
496 } // namespace mozilla