Bug 899135 - Drop buffers in ScriptProcessorNode instead of buffering them when the...
[gecko.git] / storage / src / mozStorageBindingParams.cpp
blob5f0deebfc43a67c7eb5141a4ba941fb2b523ebe4
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 * 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/. */
7 #include <limits.h>
9 #include "nsString.h"
11 #include "mozStorageError.h"
12 #include "mozStoragePrivateHelpers.h"
13 #include "mozStorageBindingParams.h"
14 #include "mozStorageBindingParamsArray.h"
15 #include "Variant.h"
17 namespace mozilla {
18 namespace storage {
20 ////////////////////////////////////////////////////////////////////////////////
21 //// Local Helper Objects
23 namespace {
25 struct BindingColumnData
27 BindingColumnData(sqlite3_stmt *aStmt,
28 int aColumn)
29 : stmt(aStmt)
30 , column(aColumn)
33 sqlite3_stmt *stmt;
34 int column;
37 ////////////////////////////////////////////////////////////////////////////////
38 //// Variant Specialization Functions (variantToSQLiteT)
40 int
41 sqlite3_T_int(BindingColumnData aData,
42 int aValue)
44 return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
47 int
48 sqlite3_T_int64(BindingColumnData aData,
49 sqlite3_int64 aValue)
51 return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
54 int
55 sqlite3_T_double(BindingColumnData aData,
56 double aValue)
58 return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
61 int
62 sqlite3_T_text(BindingColumnData aData,
63 const nsCString& aValue)
65 return ::sqlite3_bind_text(aData.stmt,
66 aData.column + 1,
67 aValue.get(),
68 aValue.Length(),
69 SQLITE_TRANSIENT);
72 int
73 sqlite3_T_text16(BindingColumnData aData,
74 const nsString& aValue)
76 return ::sqlite3_bind_text16(aData.stmt,
77 aData.column + 1,
78 aValue.get(),
79 aValue.Length() * 2, // Length in bytes!
80 SQLITE_TRANSIENT);
83 int
84 sqlite3_T_null(BindingColumnData aData)
86 return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
89 int
90 sqlite3_T_blob(BindingColumnData aData,
91 const void *aBlob,
92 int aSize)
94 return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
95 NS_Free);
99 #include "variantToSQLiteT_impl.h"
101 } // anonymous namespace
103 ////////////////////////////////////////////////////////////////////////////////
104 //// BindingParams
106 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
107 Statement *aOwningStatement)
108 : mLocked(false)
109 , mOwningArray(aOwningArray)
110 , mOwningStatement(aOwningStatement)
112 (void)mOwningStatement->GetParameterCount(&mParamCount);
113 (void)mParameters.SetCapacity(mParamCount);
116 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
117 : mLocked(false)
118 , mOwningArray(aOwningArray)
119 , mOwningStatement(nullptr)
120 , mParamCount(0)
124 AsyncBindingParams::AsyncBindingParams(
125 mozIStorageBindingParamsArray *aOwningArray
127 : BindingParams(aOwningArray)
129 mNamedParameters.Init();
132 void
133 BindingParams::lock()
135 NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
136 mLocked = true;
138 // We no longer need to hold a reference to our statement or our owning array.
139 // The array owns us at this point, and it will own a reference to the
140 // statement.
141 mOwningStatement = nullptr;
142 mOwningArray = nullptr;
145 void
146 BindingParams::unlock(Statement *aOwningStatement)
148 NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
149 mLocked = false;
150 mOwningStatement = aOwningStatement;
153 const mozIStorageBindingParamsArray *
154 BindingParams::getOwner() const
156 return mOwningArray;
159 PLDHashOperator
160 AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
161 nsIVariant *aValue,
162 void *voidClosureThunk)
164 NamedParameterIterationClosureThunk *closureThunk =
165 static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
167 // We do not accept any forms of names other than ":name", but we need to add
168 // the colon for SQLite.
169 nsAutoCString name(":");
170 name.Append(aName);
171 int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
172 name.get());
174 if (oneIdx == 0) {
175 nsAutoCString errMsg(aName);
176 errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
177 closureThunk->err = new Error(SQLITE_RANGE, errMsg.get());
178 return PL_DHASH_STOP;
181 // XPCVariant's AddRef and Release are not thread-safe and so we must not do
182 // anything that would invoke them here on the async thread. As such we can't
183 // cram aValue into self->mParameters using ReplaceObjectAt so that we can
184 // freeload off of the BindingParams::Bind implementation.
185 int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement,
186 oneIdx - 1),
187 aValue);
188 if (rc != SQLITE_OK) {
189 // We had an error while trying to bind. Now we need to create an error
190 // object with the right message. Note that we special case
191 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
192 const char *msg = "Could not covert nsIVariant to SQLite type.";
193 if (rc != SQLITE_MISMATCH)
194 msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
196 closureThunk->err = new Error(rc, msg);
197 return PL_DHASH_STOP;
199 return PL_DHASH_NEXT;
202 ////////////////////////////////////////////////////////////////////////////////
203 //// nsISupports
205 NS_IMPL_ISUPPORTS2(
206 BindingParams
207 , mozIStorageBindingParams
208 , IStorageBindingParamsInternal
212 ////////////////////////////////////////////////////////////////////////////////
213 //// IStorageBindingParamsInternal
215 already_AddRefed<mozIStorageError>
216 BindingParams::bind(sqlite3_stmt *aStatement)
218 // Iterate through all of our stored data, and bind it.
219 for (int32_t i = 0; i < mParameters.Count(); i++) {
220 int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
221 if (rc != SQLITE_OK) {
222 // We had an error while trying to bind. Now we need to create an error
223 // object with the right message. Note that we special case
224 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
225 const char *msg = "Could not covert nsIVariant to SQLite type.";
226 if (rc != SQLITE_MISMATCH)
227 msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
229 nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
230 return err.forget();
234 return nullptr;
237 already_AddRefed<mozIStorageError>
238 AsyncBindingParams::bind(sqlite3_stmt * aStatement)
240 // We should bind by index using the super-class if there is nothing in our
241 // hashtable.
242 if (!mNamedParameters.Count())
243 return BindingParams::bind(aStatement);
245 // Enumerate over everyone in the map, propagating them into mParameters if
246 // we can and creating an error immediately when we cannot.
247 NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nullptr};
248 (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
249 (void *)&closureThunk);
251 return closureThunk.err.forget();
255 ///////////////////////////////////////////////////////////////////////////////
256 //// mozIStorageBindingParams
258 NS_IMETHODIMP
259 BindingParams::BindByName(const nsACString &aName,
260 nsIVariant *aValue)
262 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
264 // Get the column index that we need to store this at.
265 uint32_t index;
266 nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
267 NS_ENSURE_SUCCESS(rv, rv);
269 return BindByIndex(index, aValue);
272 NS_IMETHODIMP
273 AsyncBindingParams::BindByName(const nsACString &aName,
274 nsIVariant *aValue)
276 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
278 mNamedParameters.Put(aName, aValue);
279 return NS_OK;
283 NS_IMETHODIMP
284 BindingParams::BindUTF8StringByName(const nsACString &aName,
285 const nsACString &aValue)
287 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
288 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
290 return BindByName(aName, value);
293 NS_IMETHODIMP
294 BindingParams::BindStringByName(const nsACString &aName,
295 const nsAString &aValue)
297 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
298 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
300 return BindByName(aName, value);
303 NS_IMETHODIMP
304 BindingParams::BindDoubleByName(const nsACString &aName,
305 double aValue)
307 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
308 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
310 return BindByName(aName, value);
313 NS_IMETHODIMP
314 BindingParams::BindInt32ByName(const nsACString &aName,
315 int32_t aValue)
317 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
318 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
320 return BindByName(aName, value);
323 NS_IMETHODIMP
324 BindingParams::BindInt64ByName(const nsACString &aName,
325 int64_t aValue)
327 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
328 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
330 return BindByName(aName, value);
333 NS_IMETHODIMP
334 BindingParams::BindNullByName(const nsACString &aName)
336 nsCOMPtr<nsIVariant> value(new NullVariant());
337 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
339 return BindByName(aName, value);
342 NS_IMETHODIMP
343 BindingParams::BindBlobByName(const nsACString &aName,
344 const uint8_t *aValue,
345 uint32_t aValueSize)
347 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
348 std::pair<const void *, int> data(
349 static_cast<const void *>(aValue),
350 int(aValueSize)
352 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
353 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
355 return BindByName(aName, value);
358 NS_IMETHODIMP
359 BindingParams::BindByIndex(uint32_t aIndex,
360 nsIVariant *aValue)
362 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
363 ENSURE_INDEX_VALUE(aIndex, mParamCount);
365 // Store the variant for later use.
366 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
367 NS_ERROR_OUT_OF_MEMORY);
368 return NS_OK;
371 NS_IMETHODIMP
372 AsyncBindingParams::BindByIndex(uint32_t aIndex,
373 nsIVariant *aValue)
375 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
376 // In the asynchronous case we do not know how many parameters there are to
377 // bind to, so we cannot check the validity of aIndex.
379 // Store the variant for later use.
380 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
381 NS_ERROR_OUT_OF_MEMORY);
382 return NS_OK;
385 NS_IMETHODIMP
386 BindingParams::BindUTF8StringByIndex(uint32_t aIndex,
387 const nsACString &aValue)
389 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
390 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
392 return BindByIndex(aIndex, value);
395 NS_IMETHODIMP
396 BindingParams::BindStringByIndex(uint32_t aIndex,
397 const nsAString &aValue)
399 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
400 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
402 return BindByIndex(aIndex, value);
405 NS_IMETHODIMP
406 BindingParams::BindDoubleByIndex(uint32_t aIndex,
407 double aValue)
409 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
410 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
412 return BindByIndex(aIndex, value);
415 NS_IMETHODIMP
416 BindingParams::BindInt32ByIndex(uint32_t aIndex,
417 int32_t aValue)
419 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
420 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
422 return BindByIndex(aIndex, value);
425 NS_IMETHODIMP
426 BindingParams::BindInt64ByIndex(uint32_t aIndex,
427 int64_t aValue)
429 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
430 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
432 return BindByIndex(aIndex, value);
435 NS_IMETHODIMP
436 BindingParams::BindNullByIndex(uint32_t aIndex)
438 nsCOMPtr<nsIVariant> value(new NullVariant());
439 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
441 return BindByIndex(aIndex, value);
444 NS_IMETHODIMP
445 BindingParams::BindBlobByIndex(uint32_t aIndex,
446 const uint8_t *aValue,
447 uint32_t aValueSize)
449 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
450 std::pair<const void *, int> data(
451 static_cast<const void *>(aValue),
452 int(aValueSize)
454 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
455 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
457 return BindByIndex(aIndex, value);
460 } // namespace storage
461 } // namespace mozilla