LCOV - code coverage report
Current view: top level - storage - mozStorageBindingParams.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 113 203 55.7 %
Date: 2017-07-14 16:53:18 Functions: 26 43 60.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #include <limits.h>
       8             : 
       9             : #include "mozilla/UniquePtrExtensions.h"
      10             : #include "nsString.h"
      11             : 
      12             : #include "mozStorageError.h"
      13             : #include "mozStoragePrivateHelpers.h"
      14             : #include "mozStorageBindingParams.h"
      15             : #include "mozStorageBindingParamsArray.h"
      16             : #include "Variant.h"
      17             : 
      18             : namespace mozilla {
      19             : namespace storage {
      20             : 
      21             : ////////////////////////////////////////////////////////////////////////////////
      22             : //// Local Helper Objects
      23             : 
      24             : namespace {
      25             : 
      26             : struct BindingColumnData
      27             : {
      28          39 :   BindingColumnData(sqlite3_stmt *aStmt,
      29             :                     int aColumn)
      30          39 :   : stmt(aStmt)
      31          39 :   , column(aColumn)
      32             :   {
      33          39 :   }
      34             :   sqlite3_stmt *stmt;
      35             :   int column;
      36             : };
      37             : 
      38             : ////////////////////////////////////////////////////////////////////////////////
      39             : //// Variant Specialization Functions (variantToSQLiteT)
      40             : 
      41             : int
      42           0 : sqlite3_T_int(BindingColumnData aData,
      43             :               int aValue)
      44             : {
      45           0 :   return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
      46             : }
      47             : 
      48             : int
      49          17 : sqlite3_T_int64(BindingColumnData aData,
      50             :                 sqlite3_int64 aValue)
      51             : {
      52          17 :   return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
      53             : }
      54             : 
      55             : int
      56           0 : sqlite3_T_double(BindingColumnData aData,
      57             :                  double aValue)
      58             : {
      59           0 :   return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
      60             : }
      61             : 
      62             : int
      63          13 : sqlite3_T_text(BindingColumnData aData,
      64             :                const nsCString& aValue)
      65             : {
      66          26 :   return ::sqlite3_bind_text(aData.stmt,
      67          13 :                              aData.column + 1,
      68             :                              aValue.get(),
      69          13 :                              aValue.Length(),
      70          13 :                              SQLITE_TRANSIENT);
      71             : }
      72             : 
      73             : int
      74           8 : sqlite3_T_text16(BindingColumnData aData,
      75             :                  const nsString& aValue)
      76             : {
      77          16 :   return ::sqlite3_bind_text16(aData.stmt,
      78           8 :                                aData.column + 1,
      79           8 :                                aValue.get(),
      80           8 :                                aValue.Length() * 2, // Length in bytes!
      81           8 :                                SQLITE_TRANSIENT);
      82             : }
      83             : 
      84             : int
      85           1 : sqlite3_T_null(BindingColumnData aData)
      86             : {
      87           1 :   return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
      88             : }
      89             : 
      90             : int
      91           0 : sqlite3_T_blob(BindingColumnData aData,
      92             :                const void *aBlob,
      93             :                int aSize)
      94             : {
      95           0 :   return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
      96           0 :                              free);
      97             : 
      98             : }
      99             : 
     100             : #include "variantToSQLiteT_impl.h"
     101             : 
     102             : } // namespace
     103             : 
     104             : ////////////////////////////////////////////////////////////////////////////////
     105             : //// BindingParams
     106             : 
     107          13 : BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
     108          13 :                              Statement *aOwningStatement)
     109             : : mLocked(false)
     110             : , mOwningArray(aOwningArray)
     111             : , mOwningStatement(aOwningStatement)
     112          13 : , mParamCount(0)
     113             : {
     114          13 :   (void)mOwningStatement->GetParameterCount(&mParamCount);
     115          13 :   mParameters.SetCapacity(mParamCount);
     116          13 : }
     117             : 
     118           6 : BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
     119             : : mLocked(false)
     120             : , mOwningArray(aOwningArray)
     121             : , mOwningStatement(nullptr)
     122           6 : , mParamCount(0)
     123             : {
     124           6 : }
     125             : 
     126           6 : AsyncBindingParams::AsyncBindingParams(
     127             :   mozIStorageBindingParamsArray *aOwningArray
     128           6 : )
     129           6 : : BindingParams(aOwningArray)
     130             : {
     131           6 : }
     132             : 
     133             : void
     134          19 : BindingParams::lock()
     135             : {
     136          19 :   NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
     137          19 :   mLocked = true;
     138             : 
     139             :   // We no longer need to hold a reference to our statement or our owning array.
     140             :   // The array owns us at this point, and it will own a reference to the
     141             :   // statement.
     142          19 :   mOwningStatement = nullptr;
     143          19 :   mOwningArray = nullptr;
     144          19 : }
     145             : 
     146             : void
     147          19 : BindingParams::unlock(Statement *aOwningStatement)
     148             : {
     149          19 :   NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
     150          19 :   mLocked = false;
     151          19 :   mOwningStatement = aOwningStatement;
     152          19 : }
     153             : 
     154             : const mozIStorageBindingParamsArray *
     155          19 : BindingParams::getOwner() const
     156             : {
     157          19 :   return mOwningArray;
     158             : }
     159             : 
     160             : ////////////////////////////////////////////////////////////////////////////////
     161             : //// nsISupports
     162             : 
     163         190 : NS_IMPL_ISUPPORTS(
     164             :   BindingParams
     165             : , mozIStorageBindingParams
     166             : , IStorageBindingParamsInternal
     167             : )
     168             : 
     169             : 
     170             : ////////////////////////////////////////////////////////////////////////////////
     171             : //// IStorageBindingParamsInternal
     172             : 
     173             : already_AddRefed<mozIStorageError>
     174          13 : BindingParams::bind(sqlite3_stmt *aStatement)
     175             : {
     176             :   // Iterate through all of our stored data, and bind it.
     177          42 :   for (size_t i = 0; i < mParameters.Length(); i++) {
     178          29 :     int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
     179          29 :     if (rc != SQLITE_OK) {
     180             :       // We had an error while trying to bind.  Now we need to create an error
     181             :       // object with the right message.  Note that we special case
     182             :       // SQLITE_MISMATCH, but otherwise get the message from SQLite.
     183           0 :       const char *msg = "Could not covert nsIVariant to SQLite type.";
     184           0 :       if (rc != SQLITE_MISMATCH)
     185           0 :         msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
     186             : 
     187           0 :       nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
     188           0 :       return err.forget();
     189             :     }
     190             :   }
     191             : 
     192          13 :   return nullptr;
     193             : }
     194             : 
     195             : already_AddRefed<mozIStorageError>
     196           6 : AsyncBindingParams::bind(sqlite3_stmt * aStatement)
     197             : {
     198             :   // We should bind by index using the super-class if there is nothing in our
     199             :   // hashtable.
     200           6 :   if (!mNamedParameters.Count())
     201           0 :     return BindingParams::bind(aStatement);
     202             : 
     203          12 :   nsCOMPtr<mozIStorageError> err;
     204             : 
     205          16 :   for (auto iter = mNamedParameters.Iter(); !iter.Done(); iter.Next()) {
     206          10 :     const nsACString &key = iter.Key();
     207             : 
     208             :     // We do not accept any forms of names other than ":name", but we need to
     209             :     // add the colon for SQLite.
     210          20 :     nsAutoCString name(":");
     211          10 :     name.Append(key);
     212          10 :     int oneIdx = ::sqlite3_bind_parameter_index(aStatement, name.get());
     213             : 
     214          10 :     if (oneIdx == 0) {
     215           0 :       nsAutoCString errMsg(key);
     216           0 :       errMsg.AppendLiteral(" is not a valid named parameter.");
     217           0 :       err = new Error(SQLITE_RANGE, errMsg.get());
     218           0 :       break;
     219             :     }
     220             : 
     221             :     // XPCVariant's AddRef and Release are not thread-safe and so we must not
     222             :     // do anything that would invoke them here on the async thread.  As such we
     223             :     // can't cram aValue into mParameters using ReplaceObjectAt so that
     224             :     // we can freeload off of the BindingParams::Bind implementation.
     225          20 :     int rc = variantToSQLiteT(BindingColumnData(aStatement, oneIdx - 1),
     226          10 :                               iter.UserData());
     227          10 :     if (rc != SQLITE_OK) {
     228             :       // We had an error while trying to bind.  Now we need to create an error
     229             :       // object with the right message.  Note that we special case
     230             :       // SQLITE_MISMATCH, but otherwise get the message from SQLite.
     231           0 :       const char *msg = "Could not covert nsIVariant to SQLite type.";
     232           0 :       if (rc != SQLITE_MISMATCH) {
     233           0 :         msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
     234             :       }
     235           0 :       err = new Error(rc, msg);
     236           0 :       break;
     237             :     }
     238             :   }
     239             : 
     240           6 :   return err.forget();
     241             : }
     242             : 
     243             : 
     244             : ///////////////////////////////////////////////////////////////////////////////
     245             : //// mozIStorageBindingParams
     246             : 
     247             : NS_IMETHODIMP
     248          27 : BindingParams::BindByName(const nsACString &aName,
     249             :                           nsIVariant *aValue)
     250             : {
     251          27 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
     252             : 
     253             :   // Get the column index that we need to store this at.
     254             :   uint32_t index;
     255          27 :   nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
     256          27 :   NS_ENSURE_SUCCESS(rv, rv);
     257             : 
     258          27 :   return BindByIndex(index, aValue);
     259             : }
     260             : 
     261             : NS_IMETHODIMP
     262          10 : AsyncBindingParams::BindByName(const nsACString &aName,
     263             :                                nsIVariant *aValue)
     264             : {
     265          10 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
     266             : 
     267          20 :   RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
     268          10 :   if (!variant)
     269           0 :     return NS_ERROR_UNEXPECTED;
     270             : 
     271          10 :   mNamedParameters.Put(aName, variant);
     272          10 :   return NS_OK;
     273             : }
     274             : 
     275             : 
     276             : NS_IMETHODIMP
     277          13 : BindingParams::BindUTF8StringByName(const nsACString &aName,
     278             :                                     const nsACString &aValue)
     279             : {
     280          26 :   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
     281          13 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     282             : 
     283          13 :   return BindByName(aName, value);
     284             : }
     285             : 
     286             : NS_IMETHODIMP
     287           1 : BindingParams::BindStringByName(const nsACString &aName,
     288             :                                 const nsAString &aValue)
     289             : {
     290           2 :   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
     291           1 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     292             : 
     293           1 :   return BindByName(aName, value);
     294             : }
     295             : 
     296             : NS_IMETHODIMP
     297           0 : BindingParams::BindDoubleByName(const nsACString &aName,
     298             :                                 double aValue)
     299             : {
     300           0 :   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
     301           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     302             : 
     303           0 :   return BindByName(aName, value);
     304             : }
     305             : 
     306             : NS_IMETHODIMP
     307           7 : BindingParams::BindInt32ByName(const nsACString &aName,
     308             :                                int32_t aValue)
     309             : {
     310          14 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
     311           7 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     312             : 
     313           7 :   return BindByName(aName, value);
     314             : }
     315             : 
     316             : NS_IMETHODIMP
     317           6 : BindingParams::BindInt64ByName(const nsACString &aName,
     318             :                                int64_t aValue)
     319             : {
     320          12 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
     321           6 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     322             : 
     323           6 :   return BindByName(aName, value);
     324             : }
     325             : 
     326             : NS_IMETHODIMP
     327           1 : BindingParams::BindNullByName(const nsACString &aName)
     328             : {
     329           2 :   nsCOMPtr<nsIVariant> value(new NullVariant());
     330           1 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     331             : 
     332           1 :   return BindByName(aName, value);
     333             : }
     334             : 
     335             : NS_IMETHODIMP
     336           0 : BindingParams::BindBlobByName(const nsACString &aName,
     337             :                               const uint8_t *aValue,
     338             :                               uint32_t aValueSize)
     339             : {
     340           0 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
     341             :   std::pair<const void *, int> data(
     342           0 :     static_cast<const void *>(aValue),
     343           0 :     int(aValueSize)
     344           0 :   );
     345           0 :   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
     346           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     347             : 
     348           0 :   return BindByName(aName, value);
     349             : }
     350             : 
     351             : NS_IMETHODIMP
     352           0 : BindingParams::BindStringAsBlobByName(const nsACString& aName,
     353             :                                       const nsAString& aValue)
     354             : {
     355           0 :   return DoBindStringAsBlobByName(this, aName, aValue);
     356             : }
     357             : 
     358             : NS_IMETHODIMP
     359           0 : BindingParams::BindUTF8StringAsBlobByName(const nsACString& aName,
     360             :                                           const nsACString& aValue)
     361             : {
     362           0 :   return DoBindStringAsBlobByName(this, aName, aValue);
     363             : }
     364             : 
     365             : 
     366             : NS_IMETHODIMP
     367           0 : BindingParams::BindAdoptedBlobByName(const nsACString &aName,
     368             :                                      uint8_t *aValue,
     369             :                                      uint32_t aValueSize)
     370             : {
     371           0 :   UniqueFreePtr<uint8_t> uniqueValue(aValue);
     372           0 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
     373           0 :   std::pair<uint8_t *, int> data(uniqueValue.release(), int(aValueSize));
     374           0 :   nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
     375             : 
     376           0 :   return BindByName(aName, value);
     377             : }
     378             : 
     379             : NS_IMETHODIMP
     380          29 : BindingParams::BindByIndex(uint32_t aIndex,
     381             :                            nsIVariant *aValue)
     382             : {
     383          29 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
     384          29 :   ENSURE_INDEX_VALUE(aIndex, mParamCount);
     385             : 
     386             :   // Store the variant for later use.
     387          58 :   RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
     388          29 :   if (!variant)
     389           0 :     return NS_ERROR_UNEXPECTED;
     390          29 :   if (mParameters.Length() <= aIndex) {
     391          25 :     (void)mParameters.SetLength(aIndex);
     392          25 :     (void)mParameters.AppendElement(variant);
     393             :   }
     394             :   else {
     395           4 :     NS_ENSURE_TRUE(mParameters.ReplaceElementAt(aIndex, variant),
     396             :                    NS_ERROR_OUT_OF_MEMORY);
     397             :   }
     398          29 :   return NS_OK;
     399             : }
     400             : 
     401             : NS_IMETHODIMP
     402           0 : AsyncBindingParams::BindByIndex(uint32_t aIndex,
     403             :                                 nsIVariant *aValue)
     404             : {
     405           0 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
     406             :   // In the asynchronous case we do not know how many parameters there are to
     407             :   // bind to, so we cannot check the validity of aIndex.
     408             : 
     409           0 :   RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
     410           0 :   if (!variant)
     411           0 :     return NS_ERROR_UNEXPECTED;
     412           0 :   if (mParameters.Length() <= aIndex) {
     413           0 :     mParameters.SetLength(aIndex);
     414           0 :     mParameters.AppendElement(variant);
     415             :   }
     416             :   else {
     417           0 :     NS_ENSURE_TRUE(mParameters.ReplaceElementAt(aIndex, variant),
     418             :                    NS_ERROR_OUT_OF_MEMORY);
     419             :   }
     420           0 :   return NS_OK;
     421             : }
     422             : 
     423             : NS_IMETHODIMP
     424           0 : BindingParams::BindUTF8StringByIndex(uint32_t aIndex,
     425             :                                      const nsACString &aValue)
     426             : {
     427           0 :   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
     428           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     429             : 
     430           0 :   return BindByIndex(aIndex, value);
     431             : }
     432             : 
     433             : NS_IMETHODIMP
     434           0 : BindingParams::BindStringByIndex(uint32_t aIndex,
     435             :                                  const nsAString &aValue)
     436             : {
     437           0 :   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
     438           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     439             : 
     440           0 :   return BindByIndex(aIndex, value);
     441             : }
     442             : 
     443             : NS_IMETHODIMP
     444           0 : BindingParams::BindDoubleByIndex(uint32_t aIndex,
     445             :                                  double aValue)
     446             : {
     447           0 :   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
     448           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     449             : 
     450           0 :   return BindByIndex(aIndex, value);
     451             : }
     452             : 
     453             : NS_IMETHODIMP
     454           1 : BindingParams::BindInt32ByIndex(uint32_t aIndex,
     455             :                                 int32_t aValue)
     456             : {
     457           2 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
     458           1 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     459             : 
     460           1 :   return BindByIndex(aIndex, value);
     461             : }
     462             : 
     463             : NS_IMETHODIMP
     464           1 : BindingParams::BindInt64ByIndex(uint32_t aIndex,
     465             :                                 int64_t aValue)
     466             : {
     467           2 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
     468           1 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     469             : 
     470           1 :   return BindByIndex(aIndex, value);
     471             : }
     472             : 
     473             : NS_IMETHODIMP
     474           0 : BindingParams::BindNullByIndex(uint32_t aIndex)
     475             : {
     476           0 :   nsCOMPtr<nsIVariant> value(new NullVariant());
     477           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     478             : 
     479           0 :   return BindByIndex(aIndex, value);
     480             : }
     481             : 
     482             : NS_IMETHODIMP
     483           0 : BindingParams::BindBlobByIndex(uint32_t aIndex,
     484             :                                const uint8_t *aValue,
     485             :                                uint32_t aValueSize)
     486             : {
     487           0 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
     488             :   std::pair<const void *, int> data(
     489           0 :     static_cast<const void *>(aValue),
     490           0 :     int(aValueSize)
     491           0 :   );
     492           0 :   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
     493           0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
     494             : 
     495           0 :   return BindByIndex(aIndex, value);
     496             : }
     497             : 
     498             : NS_IMETHODIMP
     499           0 : BindingParams::BindStringAsBlobByIndex(uint32_t aIndex, const nsAString& aValue)
     500             : {
     501           0 :   return DoBindStringAsBlobByIndex(this, aIndex, aValue);
     502             : }
     503             : 
     504             : NS_IMETHODIMP
     505           0 : BindingParams::BindUTF8StringAsBlobByIndex(uint32_t aIndex,
     506             :                                            const nsACString& aValue)
     507             : {
     508           0 :   return DoBindStringAsBlobByIndex(this, aIndex, aValue);
     509             : }
     510             : 
     511             : NS_IMETHODIMP
     512           0 : BindingParams::BindAdoptedBlobByIndex(uint32_t aIndex,
     513             :                                       uint8_t *aValue,
     514             :                                       uint32_t aValueSize)
     515             : {
     516           0 :   UniqueFreePtr<uint8_t> uniqueValue(aValue);
     517           0 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
     518           0 :   std::pair<uint8_t *, int> data(uniqueValue.release(), int(aValueSize));
     519           0 :   nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
     520             : 
     521           0 :   return BindByIndex(aIndex, value);
     522             : }
     523             : 
     524             : } // namespace storage
     525             : } // namespace mozilla

Generated by: LCOV version 1.13