storage/src/mozStorageBindingParams.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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
    26 {
    27   BindingColumnData(sqlite3_stmt *aStmt,
    28                     int aColumn)
    29   : stmt(aStmt)
    30   , column(aColumn)
    31   {
    32   }
    33   sqlite3_stmt *stmt;
    34   int column;
    35 };
    37 ////////////////////////////////////////////////////////////////////////////////
    38 //// Variant Specialization Functions (variantToSQLiteT)
    40 int
    41 sqlite3_T_int(BindingColumnData aData,
    42               int aValue)
    43 {
    44   return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
    45 }
    47 int
    48 sqlite3_T_int64(BindingColumnData aData,
    49                 sqlite3_int64 aValue)
    50 {
    51   return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
    52 }
    54 int
    55 sqlite3_T_double(BindingColumnData aData,
    56                  double aValue)
    57 {
    58   return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
    59 }
    61 int
    62 sqlite3_T_text(BindingColumnData aData,
    63                const nsCString& aValue)
    64 {
    65   return ::sqlite3_bind_text(aData.stmt,
    66                              aData.column + 1,
    67                              aValue.get(),
    68                              aValue.Length(),
    69                              SQLITE_TRANSIENT);
    70 }
    72 int
    73 sqlite3_T_text16(BindingColumnData aData,
    74                  const nsString& aValue)
    75 {
    76   return ::sqlite3_bind_text16(aData.stmt,
    77                                aData.column + 1,
    78                                aValue.get(),
    79                                aValue.Length() * 2, // Length in bytes!
    80                                SQLITE_TRANSIENT);
    81 }
    83 int
    84 sqlite3_T_null(BindingColumnData aData)
    85 {
    86   return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
    87 }
    89 int
    90 sqlite3_T_blob(BindingColumnData aData,
    91                const void *aBlob,
    92                int aSize)
    93 {
    94   return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
    95                              NS_Free);
    97 }
    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)
   111 {
   112   (void)mOwningStatement->GetParameterCount(&mParamCount);
   113   (void)mParameters.SetCapacity(mParamCount);
   114 }
   116 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
   117 : mLocked(false)
   118 , mOwningArray(aOwningArray)
   119 , mOwningStatement(nullptr)
   120 , mParamCount(0)
   121 {
   122 }
   124 AsyncBindingParams::AsyncBindingParams(
   125   mozIStorageBindingParamsArray *aOwningArray
   126 )
   127 : BindingParams(aOwningArray)
   128 {
   129 }
   131 void
   132 BindingParams::lock()
   133 {
   134   NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
   135   mLocked = true;
   137   // We no longer need to hold a reference to our statement or our owning array.
   138   // The array owns us at this point, and it will own a reference to the
   139   // statement.
   140   mOwningStatement = nullptr;
   141   mOwningArray = nullptr;
   142 }
   144 void
   145 BindingParams::unlock(Statement *aOwningStatement)
   146 {
   147   NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
   148   mLocked = false;
   149   mOwningStatement = aOwningStatement;
   150 }
   152 const mozIStorageBindingParamsArray *
   153 BindingParams::getOwner() const
   154 {
   155   return mOwningArray;
   156 }
   158 PLDHashOperator
   159 AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
   160                                                nsIVariant *aValue,
   161                                                void *voidClosureThunk)
   162 {
   163   NamedParameterIterationClosureThunk *closureThunk =
   164     static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
   166   // We do not accept any forms of names other than ":name", but we need to add
   167   // the colon for SQLite.
   168   nsAutoCString name(":");
   169   name.Append(aName);
   170   int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
   171                                               name.get());
   173   if (oneIdx == 0) {
   174     nsAutoCString errMsg(aName);
   175     errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
   176     closureThunk->err = new Error(SQLITE_RANGE, errMsg.get());
   177     return PL_DHASH_STOP;
   178   }
   180   // XPCVariant's AddRef and Release are not thread-safe and so we must not do
   181   // anything that would invoke them here on the async thread.  As such we can't
   182   // cram aValue into self->mParameters using ReplaceObjectAt so that we can
   183   // freeload off of the BindingParams::Bind implementation.
   184   int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement,
   185                                               oneIdx - 1),
   186                             aValue);
   187   if (rc != SQLITE_OK) {
   188     // We had an error while trying to bind.  Now we need to create an error
   189     // object with the right message.  Note that we special case
   190     // SQLITE_MISMATCH, but otherwise get the message from SQLite.
   191     const char *msg = "Could not covert nsIVariant to SQLite type.";
   192     if (rc != SQLITE_MISMATCH)
   193       msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
   195     closureThunk->err = new Error(rc, msg);
   196     return PL_DHASH_STOP;
   197   }
   198   return PL_DHASH_NEXT;
   199 }
   201 ////////////////////////////////////////////////////////////////////////////////
   202 //// nsISupports
   204 NS_IMPL_ISUPPORTS(
   205   BindingParams
   206 , mozIStorageBindingParams
   207 , IStorageBindingParamsInternal
   208 )
   211 ////////////////////////////////////////////////////////////////////////////////
   212 //// IStorageBindingParamsInternal
   214 already_AddRefed<mozIStorageError>
   215 BindingParams::bind(sqlite3_stmt *aStatement)
   216 {
   217   // Iterate through all of our stored data, and bind it.
   218   for (int32_t i = 0; i < mParameters.Count(); i++) {
   219     int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
   220     if (rc != SQLITE_OK) {
   221       // We had an error while trying to bind.  Now we need to create an error
   222       // object with the right message.  Note that we special case
   223       // SQLITE_MISMATCH, but otherwise get the message from SQLite.
   224       const char *msg = "Could not covert nsIVariant to SQLite type.";
   225       if (rc != SQLITE_MISMATCH)
   226         msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
   228       nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
   229       return err.forget();
   230     }
   231   }
   233   return nullptr;
   234 }
   236 already_AddRefed<mozIStorageError>
   237 AsyncBindingParams::bind(sqlite3_stmt * aStatement)
   238 {
   239   // We should bind by index using the super-class if there is nothing in our
   240   // hashtable.
   241   if (!mNamedParameters.Count())
   242     return BindingParams::bind(aStatement);
   244   // Enumerate over everyone in the map, propagating them into mParameters if
   245   // we can and creating an error immediately when we cannot.
   246   NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nullptr};
   247   (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
   248                                        (void *)&closureThunk);
   250   return closureThunk.err.forget();
   251 }
   254 ///////////////////////////////////////////////////////////////////////////////
   255 //// mozIStorageBindingParams
   257 NS_IMETHODIMP
   258 BindingParams::BindByName(const nsACString &aName,
   259                           nsIVariant *aValue)
   260 {
   261   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
   263   // Get the column index that we need to store this at.
   264   uint32_t index;
   265   nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
   266   NS_ENSURE_SUCCESS(rv, rv);
   268   return BindByIndex(index, aValue);
   269 }
   271 NS_IMETHODIMP
   272 AsyncBindingParams::BindByName(const nsACString &aName,
   273                                nsIVariant *aValue)
   274 {
   275   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
   277   mNamedParameters.Put(aName, aValue);
   278   return NS_OK;
   279 }
   282 NS_IMETHODIMP
   283 BindingParams::BindUTF8StringByName(const nsACString &aName,
   284                                     const nsACString &aValue)
   285 {
   286   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
   287   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   289   return BindByName(aName, value);
   290 }
   292 NS_IMETHODIMP
   293 BindingParams::BindStringByName(const nsACString &aName,
   294                                 const nsAString &aValue)
   295 {
   296   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
   297   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   299   return BindByName(aName, value);
   300 }
   302 NS_IMETHODIMP
   303 BindingParams::BindDoubleByName(const nsACString &aName,
   304                                 double aValue)
   305 {
   306   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
   307   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   309   return BindByName(aName, value);
   310 }
   312 NS_IMETHODIMP
   313 BindingParams::BindInt32ByName(const nsACString &aName,
   314                                int32_t aValue)
   315 {
   316   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
   317   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   319   return BindByName(aName, value);
   320 }
   322 NS_IMETHODIMP
   323 BindingParams::BindInt64ByName(const nsACString &aName,
   324                                int64_t aValue)
   325 {
   326   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
   327   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   329   return BindByName(aName, value);
   330 }
   332 NS_IMETHODIMP
   333 BindingParams::BindNullByName(const nsACString &aName)
   334 {
   335   nsCOMPtr<nsIVariant> value(new NullVariant());
   336   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   338   return BindByName(aName, value);
   339 }
   341 NS_IMETHODIMP
   342 BindingParams::BindBlobByName(const nsACString &aName,
   343                               const uint8_t *aValue,
   344                               uint32_t aValueSize)
   345 {
   346   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   347   std::pair<const void *, int> data(
   348     static_cast<const void *>(aValue),
   349     int(aValueSize)
   350   );
   351   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
   352   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   354   return BindByName(aName, value);
   355 }
   358 NS_IMETHODIMP
   359 BindingParams::BindAdoptedBlobByName(const nsACString &aName,
   360                                      uint8_t *aValue,
   361                                      uint32_t aValueSize)
   362 {
   363   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   364   std::pair<uint8_t *, int> data(
   365     aValue,
   366     int(aValueSize)
   367   );
   368   nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
   370   return BindByName(aName, value);
   371 }
   373 NS_IMETHODIMP
   374 BindingParams::BindByIndex(uint32_t aIndex,
   375                            nsIVariant *aValue)
   376 {
   377   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
   378   ENSURE_INDEX_VALUE(aIndex, mParamCount);
   380   // Store the variant for later use.
   381   NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
   382                  NS_ERROR_OUT_OF_MEMORY);
   383   return NS_OK;
   384 }
   386 NS_IMETHODIMP
   387 AsyncBindingParams::BindByIndex(uint32_t aIndex,
   388                                 nsIVariant *aValue)
   389 {
   390   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
   391   // In the asynchronous case we do not know how many parameters there are to
   392   // bind to, so we cannot check the validity of aIndex.
   394   // Store the variant for later use.
   395   NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
   396                  NS_ERROR_OUT_OF_MEMORY);
   397   return NS_OK;
   398 }
   400 NS_IMETHODIMP
   401 BindingParams::BindUTF8StringByIndex(uint32_t aIndex,
   402                                      const nsACString &aValue)
   403 {
   404   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
   405   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   407   return BindByIndex(aIndex, value);
   408 }
   410 NS_IMETHODIMP
   411 BindingParams::BindStringByIndex(uint32_t aIndex,
   412                                  const nsAString &aValue)
   413 {
   414   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
   415   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   417   return BindByIndex(aIndex, value);
   418 }
   420 NS_IMETHODIMP
   421 BindingParams::BindDoubleByIndex(uint32_t aIndex,
   422                                  double aValue)
   423 {
   424   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
   425   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   427   return BindByIndex(aIndex, value);
   428 }
   430 NS_IMETHODIMP
   431 BindingParams::BindInt32ByIndex(uint32_t aIndex,
   432                                 int32_t aValue)
   433 {
   434   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
   435   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   437   return BindByIndex(aIndex, value);
   438 }
   440 NS_IMETHODIMP
   441 BindingParams::BindInt64ByIndex(uint32_t aIndex,
   442                                 int64_t aValue)
   443 {
   444   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
   445   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   447   return BindByIndex(aIndex, value);
   448 }
   450 NS_IMETHODIMP
   451 BindingParams::BindNullByIndex(uint32_t aIndex)
   452 {
   453   nsCOMPtr<nsIVariant> value(new NullVariant());
   454   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   456   return BindByIndex(aIndex, value);
   457 }
   459 NS_IMETHODIMP
   460 BindingParams::BindBlobByIndex(uint32_t aIndex,
   461                                const uint8_t *aValue,
   462                                uint32_t aValueSize)
   463 {
   464   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   465   std::pair<const void *, int> data(
   466     static_cast<const void *>(aValue),
   467     int(aValueSize)
   468   );
   469   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
   470   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
   472   return BindByIndex(aIndex, value);
   473 }
   475 NS_IMETHODIMP
   476 BindingParams::BindAdoptedBlobByIndex(uint32_t aIndex,
   477                                       uint8_t *aValue,
   478                                       uint32_t aValueSize)
   479 {
   480   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   481   std::pair<uint8_t *, int> data(
   482     static_cast<uint8_t *>(aValue),
   483     int(aValueSize)
   484   );
   485   nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
   487   return BindByIndex(aIndex, value);
   488 }
   490 } // namespace storage
   491 } // namespace mozilla

mercurial