LCOV - app.info - storage/src/mozStorageBindingParams.cpp

LCOV - code coverage report
| Current view: | directory - storage/src - mozStorageBindingParams.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 159 | 149 | 93.7 %
| Date: | 2012-04-21 | Functions: | 38 | 36 | 94.7 %

           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
           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
          19                 :  * Mozilla Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2009
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
          25                 :  *   Andrew Sutherland <asutherland@asutherland.org>
          26                 :  *
          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.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #include <limits.h>
          42                 :
          43                 : #include "nsString.h"
          44                 :
          45                 : #include "mozStorageError.h"
          46                 : #include "mozStoragePrivateHelpers.h"
          47                 : #include "mozStorageBindingParams.h"
          48                 : #include "mozStorageBindingParamsArray.h"
          49                 : #include "Variant.h"
          50                 :
          51                 : namespace mozilla {
          52                 : namespace storage {
          53                 :
          54                 : ////////////////////////////////////////////////////////////////////////////////
          55                 : //// Local Helper Objects
          56                 :
          57                 : namespace {
          58                 :
          59                 : struct BindingColumnData
          60                 : {
          61          420266 :   BindingColumnData(sqlite3_stmt *aStmt,
          62                 :                     int aColumn)
          63                 :   : stmt(aStmt)
          64          420266 :   , column(aColumn)
          65                 :   {
          66          420266 :   }
          67                 :   sqlite3_stmt *stmt;
          68                 :   int column;
          69                 : };
          70                 :
          71                 : ////////////////////////////////////////////////////////////////////////////////
          72                 : //// Variant Specialization Functions (variantToSQLiteT)
          73                 :
          74                 : int
          75            1123 : sqlite3_T_int(BindingColumnData aData,
          76                 :               int aValue)
          77                 : {
          78            1123 :   return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
          79                 : }
          80                 :
          81                 : int
          82          228022 : sqlite3_T_int64(BindingColumnData aData,
          83                 :                 sqlite3_int64 aValue)
          84                 : {
          85          228022 :   return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
          86                 : }
          87                 :
          88                 : int
          89           12764 : sqlite3_T_double(BindingColumnData aData,
          90                 :                  double aValue)
          91                 : {
          92           12764 :   return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
          93                 : }
          94                 :
          95                 : int
          96          102975 : sqlite3_T_text(BindingColumnData aData,
          97                 :                const nsCString& aValue)
          98                 : {
          99                 :   return ::sqlite3_bind_text(aData.stmt,
         100                 :                              aData.column + 1,
         101                 :                              aValue.get(),
         102          102975 :                              aValue.Length(),
         103          102975 :                              SQLITE_TRANSIENT);
         104                 : }
         105                 :
         106                 : int
         107           41749 : sqlite3_T_text16(BindingColumnData aData,
         108                 :                  const nsString& aValue)
         109                 : {
         110                 :   return ::sqlite3_bind_text16(aData.stmt,
         111                 :                                aData.column + 1,
         112           41749 :                                aValue.get(),
         113           41749 :                                aValue.Length() * 2, // Length in bytes!
         114           83498 :                                SQLITE_TRANSIENT);
         115                 : }
         116                 :
         117                 : int
         118           25996 : sqlite3_T_null(BindingColumnData aData)
         119                 : {
         120           25996 :   return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
         121                 : }
         122                 :
         123                 : int
         124            7633 : sqlite3_T_blob(BindingColumnData aData,
         125                 :                const void *aBlob,
         126                 :                int aSize)
         127                 : {
         128                 :   return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
         129            7633 :                              NS_Free);
         130                 :
         131                 : }
         132                 :
         133                 : #include "variantToSQLiteT_impl.h"
         134                 :
         135                 : } // anonymous namespace
         136                 :
         137                 : ////////////////////////////////////////////////////////////////////////////////
         138                 : //// BindingParams
         139                 :
         140           87644 : BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
         141                 :                              Statement *aOwningStatement)
         142                 : : mLocked(false)
         143                 : , mOwningArray(aOwningArray)
         144           87644 : , mOwningStatement(aOwningStatement)
         145                 : {
         146           87644 :   (void)mOwningStatement->GetParameterCount(&mParamCount);
         147           87644 :   (void)mParameters.SetCapacity(mParamCount);
         148           87644 : }
         149                 :
         150           33153 : BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
         151                 : : mLocked(false)
         152                 : , mOwningArray(aOwningArray)
         153                 : , mOwningStatement(nsnull)
         154           33153 : , mParamCount(0)
         155                 : {
         156           33153 : }
         157                 :
         158           33153 : AsyncBindingParams::AsyncBindingParams(
         159                 :   mozIStorageBindingParamsArray *aOwningArray
         160                 : )
         161           33153 : : BindingParams(aOwningArray)
         162                 : {
         163           33153 :   mNamedParameters.Init();
         164           33153 : }
         165                 :
         166                 : void
         167          120791 : BindingParams::lock()
         168                 : {
         169          120791 :   NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
         170          120791 :   mLocked = true;
         171                 :
         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          120791 :   mOwningStatement = nsnull;
         176          120791 :   mOwningArray = nsnull;
         177          120791 : }
         178                 :
         179                 : void
         180          104645 : BindingParams::unlock(Statement *aOwningStatement)
         181                 : {
         182          104645 :   NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
         183          104645 :   mLocked = false;
         184          104645 :   mOwningStatement = aOwningStatement;
         185          104645 : }
         186                 :
         187                 : const mozIStorageBindingParamsArray *
         188          120793 : BindingParams::getOwner() const
         189                 : {
         190          120793 :   return mOwningArray;
         191                 : }
         192                 :
         193                 : PLDHashOperator
         194          184985 : AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
         195                 :                                                nsIVariant *aValue,
         196                 :                                                void *voidClosureThunk)
         197                 : {
         198                 :   NamedParameterIterationClosureThunk *closureThunk =
         199          184985 :     static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
         200                 :
         201                 :   // We do not accept any forms of names other than ":name", but we need to add
         202                 :   // the colon for SQLite.
         203          369970 :   nsCAutoString name(":");
         204          184985 :   name.Append(aName);
         205                 :   int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
         206          184985 :                                               name.get());
         207                 :
         208          184985 :   if (oneIdx == 0) {
         209               2 :     nsCAutoString errMsg(aName);
         210               1 :     errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
         211               2 :     closureThunk->err = new Error(SQLITE_RANGE, errMsg.get());
         212               1 :     return PL_DHASH_STOP;
         213                 :   }
         214                 :
         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          184984 :                             aValue);
         222          184984 :   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               1 :     const char *msg = "Could not covert nsIVariant to SQLite type.";
         227               1 :     if (rc != SQLITE_MISMATCH)
         228               0 :       msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
         229                 :
         230               1 :     closureThunk->err = new Error(rc, msg);
         231               1 :     return PL_DHASH_STOP;
         232                 :   }
         233          184983 :   return PL_DHASH_NEXT;
         234                 : }
         235                 :
         236                 : ////////////////////////////////////////////////////////////////////////////////
         237                 : //// nsISupports
         238                 :
         239         1355378 : NS_IMPL_THREADSAFE_ISUPPORTS2(
         240                 :   BindingParams
         241                 : , mozIStorageBindingParams
         242                 : , IStorageBindingParamsInternal
         243                 : )
         244                 :
         245                 :
         246                 : ////////////////////////////////////////////////////////////////////////////////
         247                 : //// IStorageBindingParamsInternal
         248                 :
         249                 : already_AddRefed<mozIStorageError>
         250           87978 : BindingParams::bind(sqlite3_stmt *aStatement)
         251                 : {
         252                 :   // Iterate through all of our stored data, and bind it.
         253          323256 :   for (PRInt32 i = 0; i < mParameters.Count(); i++) {
         254          235282 :     int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
         255          235282 :     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               4 :       const char *msg = "Could not covert nsIVariant to SQLite type.";
         260               4 :       if (rc != SQLITE_MISMATCH)
         261               1 :         msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
         262                 :
         263               8 :       nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
         264               4 :       return err.forget();
         265                 :     }
         266                 :   }
         267                 :
         268           87974 :   return nsnull;
         269                 : }
         270                 :
         271                 : already_AddRefed<mozIStorageError>
         272           33144 : AsyncBindingParams::bind(sqlite3_stmt * aStatement)
         273                 : {
         274                 :   // We should bind by index using the super-class if there is nothing in our
         275                 :   // hashtable.
         276           33144 :   if (!mNamedParameters.Count())
         277             348 :     return BindingParams::bind(aStatement);
         278                 :
         279                 :   // Enumerate over everyone in the map, propagating them into mParameters if
         280                 :   // we can and creating an error immediately when we cannot.
         281           65592 :   NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nsnull};
         282                 :   (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
         283           32796 :                                        (void *)&closureThunk);
         284                 :
         285           32796 :   return closureThunk.err.forget();
         286                 : }
         287                 :
         288                 :
         289                 : ///////////////////////////////////////////////////////////////////////////////
         290                 : //// mozIStorageBindingParams
         291                 :
         292                 : NS_IMETHODIMP
         293          230240 : BindingParams::BindByName(const nsACString &aName,
         294                 :                           nsIVariant *aValue)
         295                 : {
         296          230240 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
         297                 :
         298                 :   // Get the column index that we need to store this at.
         299                 :   PRUint32 index;
         300          230239 :   nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
         301          230239 :   NS_ENSURE_SUCCESS(rv, rv);
         302                 :
         303          230237 :   return BindByIndex(index, aValue);
         304                 : }
         305                 :
         306                 : NS_IMETHODIMP
         307          184995 : AsyncBindingParams::BindByName(const nsACString &aName,
         308                 :                                nsIVariant *aValue)
         309                 : {
         310          184995 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
         311                 :
         312          184994 :   if (!mNamedParameters.Put(aName, aValue))
         313               0 :     return NS_ERROR_OUT_OF_MEMORY;
         314          184994 :   return NS_OK;
         315                 : }
         316                 :
         317                 :
         318                 : NS_IMETHODIMP
         319          101122 : BindingParams::BindUTF8StringByName(const nsACString &aName,
         320                 :                                     const nsACString &aValue)
         321                 : {
         322          202244 :   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
         323          101122 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         324                 :
         325          101122 :   return BindByName(aName, value);
         326                 : }
         327                 :
         328                 : NS_IMETHODIMP
         329            4272 : BindingParams::BindStringByName(const nsACString &aName,
         330                 :                                 const nsAString &aValue)
         331                 : {
         332            8544 :   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
         333            4272 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         334                 :
         335            4272 :   return BindByName(aName, value);
         336                 : }
         337                 :
         338                 : NS_IMETHODIMP
         339              10 : BindingParams::BindDoubleByName(const nsACString &aName,
         340                 :                                 double aValue)
         341                 : {
         342              20 :   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
         343              10 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         344                 :
         345              10 :   return BindByName(aName, value);
         346                 : }
         347                 :
         348                 : NS_IMETHODIMP
         349           54047 : BindingParams::BindInt32ByName(const nsACString &aName,
         350                 :                                PRInt32 aValue)
         351                 : {
         352          108094 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
         353           54047 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         354                 :
         355           54047 :   return BindByName(aName, value);
         356                 : }
         357                 :
         358                 : NS_IMETHODIMP
         359          122348 : BindingParams::BindInt64ByName(const nsACString &aName,
         360                 :                                PRInt64 aValue)
         361                 : {
         362          244696 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
         363          122348 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         364                 :
         365          122348 :   return BindByName(aName, value);
         366                 : }
         367                 :
         368                 : NS_IMETHODIMP
         369            7686 : BindingParams::BindNullByName(const nsACString &aName)
         370                 : {
         371           15372 :   nsCOMPtr<nsIVariant> value(new NullVariant());
         372            7686 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         373                 :
         374            7686 :   return BindByName(aName, value);
         375                 : }
         376                 :
         377                 : NS_IMETHODIMP
         378            7560 : BindingParams::BindBlobByName(const nsACString &aName,
         379                 :                               const PRUint8 *aValue,
         380                 :                               PRUint32 aValueSize)
         381                 : {
         382            7560 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
         383                 :   std::pair<const void *, int> data(
         384                 :     static_cast<const void *>(aValue),
         385                 :     int(aValueSize)
         386            7560 :   );
         387           15120 :   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
         388            7560 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         389                 :
         390            7560 :   return BindByName(aName, value);
         391                 : }
         392                 :
         393                 : NS_IMETHODIMP
         394          234920 : BindingParams::BindByIndex(PRUint32 aIndex,
         395                 :                            nsIVariant *aValue)
         396                 : {
         397          234920 :   NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
         398          234920 :   ENSURE_INDEX_VALUE(aIndex, mParamCount);
         399                 :
         400                 :   // Store the variant for later use.
         401          234918 :   NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
         402                 :                  NS_ERROR_OUT_OF_MEMORY);
         403          234918 :   return NS_OK;
         404                 : }
         405                 :
         406                 : NS_IMETHODIMP
         407             384 : AsyncBindingParams::BindByIndex(PRUint32 aIndex,
         408                 :                                 nsIVariant *aValue)
         409                 : {
         410             384 :   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.
         413                 :
         414                 :   // Store the variant for later use.
         415             384 :   NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
         416                 :                  NS_ERROR_OUT_OF_MEMORY);
         417             384 :   return NS_OK;
         418                 : }
         419                 :
         420                 : NS_IMETHODIMP
         421            1853 : BindingParams::BindUTF8StringByIndex(PRUint32 aIndex,
         422                 :                                      const nsACString &aValue)
         423                 : {
         424            3706 :   nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
         425            1853 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         426                 :
         427            1853 :   return BindByIndex(aIndex, value);
         428                 : }
         429                 :
         430                 : NS_IMETHODIMP
         431             102 : BindingParams::BindStringByIndex(PRUint32 aIndex,
         432                 :                                  const nsAString &aValue)
         433                 : {
         434             204 :   nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
         435             102 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         436                 :
         437             102 :   return BindByIndex(aIndex, value);
         438                 : }
         439                 :
         440                 : NS_IMETHODIMP
         441               0 : BindingParams::BindDoubleByIndex(PRUint32 aIndex,
         442                 :                                  double aValue)
         443                 : {
         444               0 :   nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
         445               0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         446                 :
         447               0 :   return BindByIndex(aIndex, value);
         448                 : }
         449                 :
         450                 : NS_IMETHODIMP
         451            1239 : BindingParams::BindInt32ByIndex(PRUint32 aIndex,
         452                 :                                 PRInt32 aValue)
         453                 : {
         454            2478 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
         455            1239 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         456                 :
         457            1239 :   return BindByIndex(aIndex, value);
         458                 : }
         459                 :
         460                 : NS_IMETHODIMP
         461            1040 : BindingParams::BindInt64ByIndex(PRUint32 aIndex,
         462                 :                                 PRInt64 aValue)
         463                 : {
         464            2080 :   nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
         465            1040 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         466                 :
         467            1040 :   return BindByIndex(aIndex, value);
         468                 : }
         469                 :
         470                 : NS_IMETHODIMP
         471               0 : BindingParams::BindNullByIndex(PRUint32 aIndex)
         472                 : {
         473               0 :   nsCOMPtr<nsIVariant> value(new NullVariant());
         474               0 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         475                 :
         476               0 :   return BindByIndex(aIndex, value);
         477                 : }
         478                 :
         479                 : NS_IMETHODIMP
         480              75 : BindingParams::BindBlobByIndex(PRUint32 aIndex,
         481                 :                                const PRUint8 *aValue,
         482                 :                                PRUint32 aValueSize)
         483                 : {
         484              75 :   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
         485                 :   std::pair<const void *, int> data(
         486                 :     static_cast<const void *>(aValue),
         487                 :     int(aValueSize)
         488              75 :   );
         489             150 :   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
         490              75 :   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
         491                 :
         492              75 :   return BindByIndex(aIndex, value);
         493                 : }
         494                 :
         495                 : } // namespace storage
         496                 : } // namespace mozilla

Generated by: LCOV version 1.7