LCOV - code coverage report
Current view: directory - dom/indexedDB - IDBIndex.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 668 614 91.9 %
Date: 2012-06-02 Functions: 66 64 97.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 et sw=2 tw=80: */
       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 Indexed Database.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * The Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Shawn Wilsher <me@shawnwilsher.com>
      25                 :  *   Ben Turner <bent.mozilla@gmail.com>
      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                 : 
      42                 : #include "IDBIndex.h"
      43                 : 
      44                 : #include "nsIIDBKeyRange.h"
      45                 : #include "nsIJSContextStack.h"
      46                 : 
      47                 : #include "nsDOMClassInfoID.h"
      48                 : #include "nsEventDispatcher.h"
      49                 : #include "nsThreadUtils.h"
      50                 : #include "mozilla/storage.h"
      51                 : #include "xpcpublic.h"
      52                 : 
      53                 : #include "AsyncConnectionHelper.h"
      54                 : #include "IDBCursor.h"
      55                 : #include "IDBEvents.h"
      56                 : #include "IDBKeyRange.h"
      57                 : #include "IDBObjectStore.h"
      58                 : #include "IDBTransaction.h"
      59                 : #include "DatabaseInfo.h"
      60                 : 
      61                 : USING_INDEXEDDB_NAMESPACE
      62                 : 
      63                 : namespace {
      64                 : 
      65                 : class GetKeyHelper : public AsyncConnectionHelper
      66             146 : {
      67                 : public:
      68              61 :   GetKeyHelper(IDBTransaction* aTransaction,
      69                 :                IDBRequest* aRequest,
      70                 :                IDBIndex* aIndex,
      71                 :                IDBKeyRange* aKeyRange)
      72                 :   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
      73              61 :     mKeyRange(aKeyRange)
      74              61 :   { }
      75                 : 
      76                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
      77                 :   nsresult GetSuccessResult(JSContext* aCx,
      78                 :                             jsval* aVal);
      79                 : 
      80              61 :   void ReleaseMainThreadObjects()
      81                 :   {
      82              61 :     mIndex = nsnull;
      83              61 :     mKeyRange = nsnull;
      84              61 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
      85              61 :   }
      86                 : 
      87                 : protected:
      88                 :   // In-params.
      89                 :   nsRefPtr<IDBIndex> mIndex;
      90                 :   nsRefPtr<IDBKeyRange> mKeyRange;
      91                 : 
      92                 :   // Out-params.
      93                 :   Key mKey;
      94                 : };
      95                 : 
      96                 : class GetHelper : public GetKeyHelper
      97                 : {
      98                 : public:
      99              25 :   GetHelper(IDBTransaction* aTransaction,
     100                 :             IDBRequest* aRequest,
     101                 :             IDBIndex* aIndex,
     102                 :             IDBKeyRange* aKeyRange)
     103              25 :   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange)
     104              25 :   { }
     105                 : 
     106              50 :   ~GetHelper()
     107              50 :   {
     108              25 :     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
     109             100 :   }
     110                 : 
     111                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     112                 :   nsresult GetSuccessResult(JSContext* aCx,
     113                 :                             jsval* aVal);
     114                 : 
     115              25 :   void ReleaseMainThreadObjects()
     116                 :   {
     117              25 :     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
     118              25 :     GetKeyHelper::ReleaseMainThreadObjects();
     119              25 :   }
     120                 : 
     121                 : protected:
     122                 :   StructuredCloneReadInfo mCloneReadInfo;
     123                 : };
     124                 : 
     125                 : class GetAllKeysHelper : public GetKeyHelper
     126              48 : {
     127                 : public:
     128              12 :   GetAllKeysHelper(IDBTransaction* aTransaction,
     129                 :                    IDBRequest* aRequest,
     130                 :                    IDBIndex* aIndex,
     131                 :                    IDBKeyRange* aKeyRange,
     132                 :                    const PRUint32 aLimit)
     133              12 :   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
     134              12 :   { }
     135                 : 
     136                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     137                 :   nsresult GetSuccessResult(JSContext* aCx,
     138                 :                             jsval* aVal);
     139                 : 
     140                 : protected:
     141                 :   const PRUint32 mLimit;
     142                 :   nsTArray<Key> mKeys;
     143                 : };
     144                 : 
     145                 : class GetAllHelper : public GetKeyHelper
     146                 : {
     147                 : public:
     148              12 :   GetAllHelper(IDBTransaction* aTransaction,
     149                 :                IDBRequest* aRequest,
     150                 :                IDBIndex* aIndex,
     151                 :                IDBKeyRange* aKeyRange,
     152                 :                const PRUint32 aLimit)
     153              12 :   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
     154              12 :   { }
     155                 : 
     156              24 :   ~GetAllHelper()
     157              24 :   {
     158              12 :     for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
     159                 :       IDBObjectStore::ClearStructuredCloneBuffer(
     160               0 :         mCloneReadInfos[index].mCloneBuffer);
     161                 :     }
     162              48 :   }
     163                 : 
     164                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     165                 :   nsresult GetSuccessResult(JSContext* aCx,
     166                 :                             jsval* aVal);
     167                 : 
     168              12 :   void ReleaseMainThreadObjects()
     169                 :   {
     170              12 :     for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
     171                 :       IDBObjectStore::ClearStructuredCloneBuffer(
     172               0 :         mCloneReadInfos[index].mCloneBuffer);
     173                 :     }
     174              12 :     GetKeyHelper::ReleaseMainThreadObjects();
     175              12 :   }
     176                 : 
     177                 : protected:
     178                 :   const PRUint32 mLimit;
     179                 :   nsTArray<StructuredCloneReadInfo> mCloneReadInfos;
     180                 : };
     181                 : 
     182                 : class OpenKeyCursorHelper : public AsyncConnectionHelper
     183             356 : {
     184                 : public:
     185              89 :   OpenKeyCursorHelper(IDBTransaction* aTransaction,
     186                 :                       IDBRequest* aRequest,
     187                 :                       IDBIndex* aIndex,
     188                 :                       IDBKeyRange* aKeyRange,
     189                 :                       IDBCursor::Direction aDirection)
     190                 :   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
     191              89 :     mKeyRange(aKeyRange), mDirection(aDirection)
     192              89 :   { }
     193                 : 
     194                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     195                 :   nsresult GetSuccessResult(JSContext* aCx,
     196                 :                             jsval* aVal);
     197                 : 
     198              89 :   void ReleaseMainThreadObjects()
     199                 :   {
     200              89 :     mIndex = nsnull;
     201              89 :     mKeyRange = nsnull;
     202              89 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
     203              89 :   }
     204                 : 
     205                 : private:
     206                 :   // In-params.
     207                 :   nsRefPtr<IDBIndex> mIndex;
     208                 :   nsRefPtr<IDBKeyRange> mKeyRange;
     209                 :   const IDBCursor::Direction mDirection;
     210                 : 
     211                 :   // Out-params.
     212                 :   Key mKey;
     213                 :   Key mObjectKey;
     214                 :   nsCString mContinueQuery;
     215                 :   nsCString mContinueToQuery;
     216                 :   Key mRangeKey;
     217                 : };
     218                 : 
     219                 : class OpenCursorHelper : public AsyncConnectionHelper
     220                 : {
     221                 : public:
     222              57 :   OpenCursorHelper(IDBTransaction* aTransaction,
     223                 :                    IDBRequest* aRequest,
     224                 :                    IDBIndex* aIndex,
     225                 :                    IDBKeyRange* aKeyRange,
     226                 :                    IDBCursor::Direction aDirection)
     227                 :   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
     228              57 :     mKeyRange(aKeyRange), mDirection(aDirection)
     229              57 :   { }
     230                 : 
     231             114 :   ~OpenCursorHelper()
     232             114 :   {
     233              57 :     IDBObjectStore::ClearStructuredCloneBuffer(mCloneReadInfo.mCloneBuffer);
     234             228 :   }
     235                 : 
     236                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     237                 :   nsresult GetSuccessResult(JSContext* aCx,
     238                 :                             jsval* aVal);
     239                 : 
     240              57 :   void ReleaseMainThreadObjects()
     241                 :   {
     242              57 :     mIndex = nsnull;
     243              57 :     mKeyRange = nsnull;
     244              57 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
     245              57 :   }
     246                 : 
     247                 : private:
     248                 :   // In-params.
     249                 :   nsRefPtr<IDBIndex> mIndex;
     250                 :   nsRefPtr<IDBKeyRange> mKeyRange;
     251                 :   const IDBCursor::Direction mDirection;
     252                 : 
     253                 :   // Out-params.
     254                 :   Key mKey;
     255                 :   Key mObjectKey;
     256                 :   StructuredCloneReadInfo mCloneReadInfo;
     257                 :   nsCString mContinueQuery;
     258                 :   nsCString mContinueToQuery;
     259                 :   Key mRangeKey;
     260                 : };
     261                 : 
     262                 : class CountHelper : public AsyncConnectionHelper
     263             156 : {
     264                 : public:
     265              39 :   CountHelper(IDBTransaction* aTransaction,
     266                 :               IDBRequest* aRequest,
     267                 :               IDBIndex* aIndex,
     268                 :               IDBKeyRange* aKeyRange)
     269                 :   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
     270              39 :     mKeyRange(aKeyRange), mCount(0)
     271              39 :   { }
     272                 : 
     273                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
     274                 :   nsresult GetSuccessResult(JSContext* aCx,
     275                 :                             jsval* aVal);
     276                 : 
     277              39 :   void ReleaseMainThreadObjects()
     278                 :   {
     279              39 :     mIndex = nsnull;
     280              39 :     mKeyRange = nsnull;
     281              39 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
     282              39 :   }
     283                 : 
     284                 : private:
     285                 :   nsRefPtr<IDBIndex> mIndex;
     286                 :   nsRefPtr<IDBKeyRange> mKeyRange;
     287                 :   PRUint64 mCount;
     288                 : };
     289                 : 
     290                 : inline
     291                 : already_AddRefed<IDBRequest>
     292             246 : GenerateRequest(IDBIndex* aIndex)
     293                 : {
     294             246 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     295             246 :   IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
     296             246 :   IDBDatabase* database = transaction->Database();
     297             246 :   return IDBRequest::Create(aIndex, database, transaction);
     298                 : }
     299                 : 
     300                 : } // anonymous namespace
     301                 : 
     302                 : // static
     303                 : already_AddRefed<IDBIndex>
     304             129 : IDBIndex::Create(IDBObjectStore* aObjectStore,
     305                 :                  const IndexInfo* aIndexInfo)
     306                 : {
     307             129 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     308             129 :   NS_ASSERTION(aObjectStore, "Null pointer!");
     309             129 :   NS_ASSERTION(aIndexInfo, "Null pointer!");
     310                 : 
     311             258 :   nsRefPtr<IDBIndex> index = new IDBIndex();
     312                 : 
     313             129 :   index->mObjectStore = aObjectStore;
     314             129 :   index->mId = aIndexInfo->id;
     315             129 :   index->mName = aIndexInfo->name;
     316             129 :   index->mKeyPath = aIndexInfo->keyPath;
     317             129 :   index->mKeyPathArray = aIndexInfo->keyPathArray;
     318             129 :   index->mUnique = aIndexInfo->unique;
     319             129 :   index->mMultiEntry = aIndexInfo->multiEntry;
     320                 : 
     321             129 :   return index.forget();
     322                 : }
     323                 : 
     324             129 : IDBIndex::IDBIndex()
     325                 : : mId(LL_MININT),
     326             129 :   mUnique(false)
     327                 : {
     328             129 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     329             129 : }
     330                 : 
     331             258 : IDBIndex::~IDBIndex()
     332                 : {
     333             129 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     334             129 : }
     335                 : 
     336            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
     337                 : 
     338             105 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
     339             105 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObjectStore)
     340             105 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     341                 : 
     342             105 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
     343                 :   // Don't unlink mObjectStore!
     344             105 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     345                 : 
     346            3288 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
     347            1653 :   NS_INTERFACE_MAP_ENTRY(nsIIDBIndex)
     348            1044 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBIndex)
     349             915 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     350             738 : NS_INTERFACE_MAP_END
     351                 : 
     352            1899 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
     353            2028 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
     354                 : 
     355                 : DOMCI_DATA(IDBIndex, IDBIndex)
     356                 : 
     357                 : NS_IMETHODIMP
     358              15 : IDBIndex::GetName(nsAString& aName)
     359                 : {
     360              15 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     361                 : 
     362              15 :   aName.Assign(mName);
     363              15 :   return NS_OK;
     364                 : }
     365                 : 
     366                 : NS_IMETHODIMP
     367               3 : IDBIndex::GetStoreName(nsAString& aStoreName)
     368                 : {
     369               3 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     370                 : 
     371               3 :   return mObjectStore->GetName(aStoreName);
     372                 : }
     373                 : 
     374                 : NS_IMETHODIMP
     375              15 : IDBIndex::GetKeyPath(JSContext* aCx,
     376                 :                      jsval* aVal)
     377                 : {
     378              15 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     379                 : 
     380              15 :   if (UsesKeyPathArray()) {
     381               0 :     JSObject* array = JS_NewArrayObject(aCx, mKeyPathArray.Length(), nsnull);
     382               0 :     if (!array) {
     383               0 :       NS_WARNING("Failed to make array!");
     384               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     385                 :     }
     386                 : 
     387               0 :     for (PRUint32 i = 0; i < mKeyPathArray.Length(); ++i) {
     388                 :       jsval val;
     389               0 :       nsString tmp(mKeyPathArray[i]);
     390               0 :       if (!xpc::StringToJsval(aCx, tmp, &val)) {
     391               0 :         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     392                 :       }
     393                 : 
     394               0 :       if (!JS_SetElement(aCx, array, i, &val)) {
     395               0 :         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     396                 :       }
     397                 :     }
     398                 : 
     399               0 :     *aVal = OBJECT_TO_JSVAL(array);
     400                 :   }
     401                 :   else {
     402              30 :     nsString tmp(mKeyPath);
     403              15 :     if (!xpc::StringToJsval(aCx, tmp, aVal)) {
     404               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     405                 :     }
     406                 :   }
     407              15 :   return NS_OK;
     408                 : }
     409                 : 
     410                 : NS_IMETHODIMP
     411              15 : IDBIndex::GetUnique(bool* aUnique)
     412                 : {
     413              15 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     414                 : 
     415              15 :   *aUnique = mUnique;
     416              15 :   return NS_OK;
     417                 : }
     418                 : 
     419                 : NS_IMETHODIMP
     420               3 : IDBIndex::GetMultiEntry(bool* aMultiEntry)
     421                 : {
     422               3 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     423                 : 
     424               3 :   *aMultiEntry = mMultiEntry;
     425               3 :   return NS_OK;
     426                 : }
     427                 : 
     428                 : NS_IMETHODIMP
     429               0 : IDBIndex::GetObjectStore(nsIIDBObjectStore** aObjectStore)
     430                 : {
     431               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     432                 : 
     433               0 :   nsCOMPtr<nsIIDBObjectStore> objectStore(mObjectStore);
     434               0 :   objectStore.forget(aObjectStore);
     435               0 :   return NS_OK;
     436                 : }
     437                 : 
     438                 : NS_IMETHODIMP
     439              27 : IDBIndex::Get(const jsval& aKey,
     440                 :               JSContext* aCx,
     441                 :               nsIIDBRequest** _retval)
     442                 : {
     443              27 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     444                 : 
     445              27 :   IDBTransaction* transaction = mObjectStore->Transaction();
     446              27 :   if (!transaction->IsOpen()) {
     447               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     448                 :   }
     449                 : 
     450              54 :   nsRefPtr<IDBKeyRange> keyRange;
     451              27 :   nsresult rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     452              27 :   NS_ENSURE_SUCCESS(rv, rv);
     453                 : 
     454              27 :   if (!keyRange) {
     455                 :     // Must specify a key or keyRange for get().
     456               2 :     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
     457                 :   }
     458                 : 
     459              50 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     460              25 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     461                 : 
     462                 :   nsRefPtr<GetHelper> helper =
     463              75 :     new GetHelper(transaction, request, this, keyRange);
     464              25 :   rv = helper->DispatchToTransactionPool();
     465              25 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     466                 : 
     467              25 :   request.forget(_retval);
     468              25 :   return NS_OK;
     469                 : }
     470                 : 
     471                 : NS_IMETHODIMP
     472              14 : IDBIndex::GetKey(const jsval& aKey,
     473                 :                  JSContext* aCx,
     474                 :                  nsIIDBRequest** _retval)
     475                 : {
     476              14 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     477                 : 
     478              14 :   IDBTransaction* transaction = mObjectStore->Transaction();
     479              14 :   if (!transaction->IsOpen()) {
     480               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     481                 :   }
     482                 : 
     483              28 :   nsRefPtr<IDBKeyRange> keyRange;
     484              14 :   nsresult rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     485              14 :   NS_ENSURE_SUCCESS(rv, rv);
     486                 : 
     487              14 :   if (!keyRange) {
     488                 :     // Must specify a key or keyRange for get().
     489               2 :     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
     490                 :   }
     491                 : 
     492              24 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     493              12 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     494                 : 
     495                 :   nsRefPtr<GetKeyHelper> helper =
     496              36 :     new GetKeyHelper(transaction, request, this, keyRange);
     497                 : 
     498              12 :   rv = helper->DispatchToTransactionPool();
     499              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     500                 : 
     501              12 :   request.forget(_retval);
     502              12 :   return NS_OK;
     503                 : }
     504                 : 
     505                 : NS_IMETHODIMP
     506              12 : IDBIndex::GetAll(const jsval& aKey,
     507                 :                  PRUint32 aLimit,
     508                 :                  JSContext* aCx,
     509                 :                  PRUint8 aOptionalArgCount,
     510                 :                  nsIIDBRequest** _retval)
     511                 : {
     512              12 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     513                 : 
     514              12 :   IDBTransaction* transaction = mObjectStore->Transaction();
     515              12 :   if (!transaction->IsOpen()) {
     516               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     517                 :   }
     518                 : 
     519                 :   nsresult rv;
     520                 : 
     521              24 :   nsRefPtr<IDBKeyRange> keyRange;
     522              12 :   if (aOptionalArgCount) {
     523              10 :     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     524              10 :     NS_ENSURE_SUCCESS(rv, rv);
     525                 :   }
     526                 : 
     527              12 :   if (aOptionalArgCount < 2 || aLimit == 0) {
     528              10 :     aLimit = PR_UINT32_MAX;
     529                 :   }
     530                 : 
     531              24 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     532              12 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     533                 : 
     534                 :   nsRefPtr<GetAllHelper> helper =
     535              36 :     new GetAllHelper(transaction, request, this, keyRange, aLimit);
     536                 : 
     537              12 :   rv = helper->DispatchToTransactionPool();
     538              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     539                 : 
     540              12 :   request.forget(_retval);
     541              12 :   return NS_OK;
     542                 : }
     543                 : 
     544                 : NS_IMETHODIMP
     545              12 : IDBIndex::GetAllKeys(const jsval& aKey,
     546                 :                      PRUint32 aLimit,
     547                 :                      JSContext* aCx,
     548                 :                      PRUint8 aOptionalArgCount,
     549                 :                      nsIIDBRequest** _retval)
     550                 : {
     551              12 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     552                 : 
     553              12 :   IDBTransaction* transaction = mObjectStore->Transaction();
     554              12 :   if (!transaction->IsOpen()) {
     555               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     556                 :   }
     557                 : 
     558                 :   nsresult rv;
     559                 : 
     560              24 :   nsRefPtr<IDBKeyRange> keyRange;
     561              12 :   if (aOptionalArgCount) {
     562              10 :     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     563              10 :     NS_ENSURE_SUCCESS(rv, rv);
     564                 :   }
     565                 : 
     566              12 :   if (aOptionalArgCount < 2 || aLimit == 0) {
     567              10 :     aLimit = PR_UINT32_MAX;
     568                 :   }
     569                 : 
     570              24 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     571              12 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     572                 : 
     573                 :   nsRefPtr<GetAllKeysHelper> helper =
     574              36 :     new GetAllKeysHelper(transaction, request, this, keyRange, aLimit);
     575                 : 
     576              12 :   rv = helper->DispatchToTransactionPool();
     577              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     578                 : 
     579              12 :   request.forget(_retval);
     580              12 :   return NS_OK;
     581                 : }
     582                 : 
     583                 : NS_IMETHODIMP
     584              57 : IDBIndex::OpenCursor(const jsval& aKey,
     585                 :                      const nsAString& aDirection,
     586                 :                      JSContext* aCx,
     587                 :                      PRUint8 aOptionalArgCount,
     588                 :                      nsIIDBRequest** _retval)
     589                 : {
     590              57 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     591                 : 
     592              57 :   IDBTransaction* transaction = mObjectStore->Transaction();
     593              57 :   if (!transaction->IsOpen()) {
     594               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     595                 :   }
     596                 : 
     597                 :   nsresult rv;
     598                 : 
     599              57 :   IDBCursor::Direction direction = IDBCursor::NEXT;
     600                 : 
     601             114 :   nsRefPtr<IDBKeyRange> keyRange;
     602              57 :   if (aOptionalArgCount) {
     603              39 :     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     604              39 :     NS_ENSURE_SUCCESS(rv, rv);
     605                 : 
     606              39 :     if (aOptionalArgCount >= 2) {
     607               6 :       rv = IDBCursor::ParseDirection(aDirection, &direction);
     608               6 :       NS_ENSURE_SUCCESS(rv, rv);
     609                 :     }
     610                 :   }
     611                 : 
     612             114 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     613              57 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     614                 : 
     615                 :   nsRefPtr<OpenCursorHelper> helper =
     616             171 :     new OpenCursorHelper(transaction, request, this, keyRange, direction);
     617                 : 
     618              57 :   rv = helper->DispatchToTransactionPool();
     619              57 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     620                 : 
     621              57 :   request.forget(_retval);
     622              57 :   return NS_OK;
     623                 : }
     624                 : 
     625                 : NS_IMETHODIMP
     626              89 : IDBIndex::OpenKeyCursor(const jsval& aKey,
     627                 :                         const nsAString& aDirection,
     628                 :                         JSContext* aCx,
     629                 :                         PRUint8 aOptionalArgCount,
     630                 :                         nsIIDBRequest** _retval)
     631                 : {
     632              89 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     633                 : 
     634              89 :   IDBTransaction* transaction = mObjectStore->Transaction();
     635              89 :   if (!transaction->IsOpen()) {
     636               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     637                 :   }
     638                 : 
     639                 :   nsresult rv;
     640                 : 
     641              89 :   IDBCursor::Direction direction = IDBCursor::NEXT;
     642                 : 
     643             178 :   nsRefPtr<IDBKeyRange> keyRange;
     644              89 :   if (aOptionalArgCount) {
     645              41 :     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     646              41 :     NS_ENSURE_SUCCESS(rv, rv);
     647                 : 
     648              41 :     if (aOptionalArgCount >= 2) {
     649               6 :       rv = IDBCursor::ParseDirection(aDirection, &direction);
     650               6 :       NS_ENSURE_SUCCESS(rv, rv);
     651                 :     }
     652                 :   }
     653                 : 
     654             178 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     655              89 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     656                 : 
     657                 :   nsRefPtr<OpenKeyCursorHelper> helper =
     658             267 :     new OpenKeyCursorHelper(transaction, request, this, keyRange, direction);
     659                 : 
     660              89 :   rv = helper->DispatchToTransactionPool();
     661              89 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     662                 : 
     663              89 :   request.forget(_retval);
     664              89 :   return NS_OK;
     665                 : }
     666                 : 
     667                 : NS_IMETHODIMP
     668              39 : IDBIndex::Count(const jsval& aKey,
     669                 :                 JSContext* aCx,
     670                 :                 PRUint8 aOptionalArgCount,
     671                 :                 nsIIDBRequest** _retval)
     672                 : {
     673              39 :   IDBTransaction* transaction = mObjectStore->Transaction();
     674              39 :   if (!transaction->IsOpen()) {
     675               0 :     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
     676                 :   }
     677                 : 
     678                 :   nsresult rv;
     679                 : 
     680              78 :   nsRefPtr<IDBKeyRange> keyRange;
     681              39 :   if (aOptionalArgCount) {
     682              22 :     rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
     683              22 :     NS_ENSURE_SUCCESS(rv, rv);
     684                 :   }
     685                 : 
     686              78 :   nsRefPtr<IDBRequest> request = GenerateRequest(this);
     687              39 :   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     688                 : 
     689                 :   nsRefPtr<CountHelper> helper =
     690             117 :     new CountHelper(transaction, request, this, keyRange);
     691              39 :   rv = helper->DispatchToTransactionPool();
     692              39 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     693                 : 
     694              39 :   request.forget(_retval);
     695              39 :   return NS_OK;
     696                 : }
     697                 : 
     698                 : nsresult
     699              12 : GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
     700                 : {
     701              12 :   NS_ASSERTION(mKeyRange, "Must have a key range here!");
     702                 : 
     703              24 :   nsCString indexTable;
     704              12 :   if (mIndex->IsUnique()) {
     705               1 :     indexTable.AssignLiteral("unique_index_data");
     706                 :   }
     707                 :   else {
     708              11 :     indexTable.AssignLiteral("index_data");
     709                 :   }
     710                 : 
     711              24 :   nsCString keyRangeClause;
     712              12 :   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
     713                 : 
     714              12 :   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
     715                 : 
     716              12 :   nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
     717              12 :                     indexTable +
     718              36 :                     NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
     719              12 :                     keyRangeClause +
     720              48 :                     NS_LITERAL_CSTRING(" LIMIT 1");
     721                 : 
     722              24 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
     723              12 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     724                 : 
     725              24 :   mozStorageStatementScoper scoper(stmt);
     726                 : 
     727              24 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
     728              12 :                                       mIndex->Id());
     729              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     730                 : 
     731              12 :   rv = mKeyRange->BindToStatement(stmt);
     732              12 :   NS_ENSURE_SUCCESS(rv, rv);
     733                 : 
     734                 :   bool hasResult;
     735              12 :   rv = stmt->ExecuteStep(&hasResult);
     736              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     737                 : 
     738              12 :   if (hasResult) {
     739              10 :     rv = mKey.SetFromStatement(stmt, 0);
     740              10 :     NS_ENSURE_SUCCESS(rv, rv);
     741                 :   }
     742                 : 
     743              12 :   return NS_OK;
     744                 : }
     745                 : 
     746                 : nsresult
     747              12 : GetKeyHelper::GetSuccessResult(JSContext* aCx,
     748                 :                                jsval* aVal)
     749                 : {
     750              12 :   return mKey.ToJSVal(aCx, aVal);
     751                 : }
     752                 : 
     753                 : nsresult
     754              25 : GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
     755                 : {
     756              25 :   NS_ASSERTION(mKeyRange, "Must have a key range here!");
     757                 : 
     758              50 :   nsCString indexTable;
     759              25 :   if (mIndex->IsUnique()) {
     760               7 :     indexTable.AssignLiteral("unique_index_data");
     761                 :   }
     762                 :   else {
     763              18 :     indexTable.AssignLiteral("index_data");
     764                 :   }
     765                 : 
     766              50 :   nsCString keyRangeClause;
     767              25 :   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
     768                 : 
     769              25 :   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
     770                 : 
     771              25 :   nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
     772              25 :                                        "INNER JOIN ") + indexTable +
     773              75 :                     NS_LITERAL_CSTRING(" AS index_table ON object_data.id = ") +
     774              75 :                     NS_LITERAL_CSTRING("index_table.object_data_id WHERE "
     775                 :                                        "index_id = :index_id") +
     776              25 :                     keyRangeClause +
     777             100 :                     NS_LITERAL_CSTRING(" LIMIT 1");
     778                 : 
     779              50 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
     780              25 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     781                 : 
     782              50 :   mozStorageStatementScoper scoper(stmt);
     783                 : 
     784              50 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
     785              25 :                                       mIndex->Id());
     786              25 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     787                 : 
     788              25 :   rv = mKeyRange->BindToStatement(stmt);
     789              25 :   NS_ENSURE_SUCCESS(rv, rv);
     790                 : 
     791                 :   bool hasResult;
     792              25 :   rv = stmt->ExecuteStep(&hasResult);
     793              25 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     794                 : 
     795              25 :   if (hasResult) {
     796                 :     rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
     797              23 :       mDatabase->Manager(), mCloneReadInfo);
     798              23 :     NS_ENSURE_SUCCESS(rv, rv);
     799                 :   }
     800                 : 
     801              25 :   return NS_OK;
     802                 : }
     803                 : 
     804                 : nsresult
     805              25 : GetHelper::GetSuccessResult(JSContext* aCx,
     806                 :                             jsval* aVal)
     807                 : {
     808              25 :   bool result = IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, aVal);
     809                 : 
     810              25 :   mCloneReadInfo.mCloneBuffer.clear();
     811                 : 
     812              25 :   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
     813              25 :   return NS_OK;
     814                 : }
     815                 : 
     816                 : nsresult
     817              12 : GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
     818                 : {
     819              24 :   nsCString tableName;
     820              12 :   if (mIndex->IsUnique()) {
     821               0 :     tableName.AssignLiteral("unique_index_data");
     822                 :   }
     823                 :   else {
     824              12 :     tableName.AssignLiteral("index_data");
     825                 :   }
     826                 : 
     827              24 :   nsCString keyRangeClause;
     828              12 :   if (mKeyRange) {
     829               7 :     mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
     830                 :   }
     831                 : 
     832              24 :   nsCString limitClause;
     833              12 :   if (mLimit != PR_UINT32_MAX) {
     834               2 :     limitClause = NS_LITERAL_CSTRING(" LIMIT ");
     835               2 :     limitClause.AppendInt(mLimit);
     836                 :   }
     837                 : 
     838              12 :   nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
     839              12 :                     tableName +
     840              36 :                     NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
     841              24 :                     keyRangeClause + limitClause;
     842                 : 
     843              24 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
     844              12 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     845                 : 
     846              24 :   mozStorageStatementScoper scoper(stmt);
     847                 : 
     848              24 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
     849              12 :                                       mIndex->Id());
     850              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     851                 : 
     852              12 :   if (mKeyRange) {
     853               7 :     rv = mKeyRange->BindToStatement(stmt);
     854               7 :     NS_ENSURE_SUCCESS(rv, rv);
     855                 :   }
     856                 : 
     857              12 :   mKeys.SetCapacity(50);
     858                 : 
     859                 :   bool hasResult;
     860              12 :   while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
     861              44 :     if (mKeys.Capacity() == mKeys.Length()) {
     862               0 :       mKeys.SetCapacity(mKeys.Capacity() * 2);
     863                 :     }
     864                 : 
     865              44 :     Key* key = mKeys.AppendElement();
     866              44 :     NS_ASSERTION(key, "This shouldn't fail!");
     867                 : 
     868              44 :     rv = key->SetFromStatement(stmt, 0);
     869              44 :     NS_ENSURE_SUCCESS(rv, rv);
     870                 :   }
     871              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     872                 : 
     873              12 :   return NS_OK;
     874                 : }
     875                 : 
     876                 : nsresult
     877              12 : GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
     878                 :                                    jsval* aVal)
     879                 : {
     880              12 :   NS_ASSERTION(mKeys.Length() <= mLimit, "Too many results!");
     881                 : 
     882              24 :   nsTArray<Key> keys;
     883              12 :   if (!mKeys.SwapElements(keys)) {
     884               0 :     NS_ERROR("Failed to swap elements!");
     885               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     886                 :   }
     887                 : 
     888              24 :   JSAutoRequest ar(aCx);
     889                 : 
     890              12 :   JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
     891              12 :   if (!array) {
     892               0 :     NS_WARNING("Failed to make array!");
     893               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     894                 :   }
     895                 : 
     896              12 :   if (!keys.IsEmpty()) {
     897              12 :     if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
     898               0 :       NS_WARNING("Failed to set array length!");
     899               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     900                 :     }
     901                 : 
     902              56 :     for (uint32 index = 0, count = keys.Length(); index < count; index++) {
     903              44 :       const Key& key = keys[index];
     904              44 :       NS_ASSERTION(!key.IsUnset(), "Bad key!");
     905                 : 
     906                 :       jsval value;
     907              44 :       nsresult rv = key.ToJSVal(aCx, &value);
     908              44 :       if (NS_FAILED(rv)) {
     909               0 :         NS_WARNING("Failed to get jsval for key!");
     910               0 :         return rv;
     911                 :       }
     912                 : 
     913              44 :       if (!JS_SetElement(aCx, array, index, &value)) {
     914               0 :         NS_WARNING("Failed to set array element!");
     915               0 :         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     916                 :       }
     917                 :     }
     918                 :   }
     919                 : 
     920              12 :   *aVal = OBJECT_TO_JSVAL(array);
     921              12 :   return NS_OK;
     922                 : }
     923                 : 
     924                 : nsresult
     925              12 : GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
     926                 : {
     927              24 :   nsCString indexTable;
     928              12 :   if (mIndex->IsUnique()) {
     929               0 :     indexTable.AssignLiteral("unique_index_data");
     930                 :   }
     931                 :   else {
     932              12 :     indexTable.AssignLiteral("index_data");
     933                 :   }
     934                 : 
     935              24 :   nsCString keyRangeClause;
     936              12 :   if (mKeyRange) {
     937               7 :     mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
     938                 :   }
     939                 : 
     940              24 :   nsCString limitClause;
     941              12 :   if (mLimit != PR_UINT32_MAX) {
     942               2 :     limitClause = NS_LITERAL_CSTRING(" LIMIT ");
     943               2 :     limitClause.AppendInt(mLimit);
     944                 :   }
     945                 : 
     946              12 :   nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
     947              12 :                                        "INNER JOIN ") + indexTable +
     948              36 :                     NS_LITERAL_CSTRING(" AS index_table ON object_data.id = "
     949                 :                                        "index_table.object_data_id "
     950                 :                                        "WHERE index_id = :index_id") +
     951              24 :                     keyRangeClause + limitClause;
     952                 : 
     953              24 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
     954              12 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     955                 : 
     956              24 :   mozStorageStatementScoper scoper(stmt);
     957                 : 
     958              24 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
     959              12 :                                       mIndex->Id());
     960              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     961                 : 
     962              12 :   if (mKeyRange) {
     963               7 :     rv = mKeyRange->BindToStatement(stmt);
     964               7 :     NS_ENSURE_SUCCESS(rv, rv);
     965                 :   }
     966                 : 
     967              12 :   mCloneReadInfos.SetCapacity(50);
     968                 : 
     969                 :   bool hasResult;
     970              12 :   while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
     971              44 :     if (mCloneReadInfos.Capacity() == mCloneReadInfos.Length()) {
     972               0 :       mCloneReadInfos.SetCapacity(mCloneReadInfos.Capacity() * 2);
     973                 :     }
     974                 : 
     975              44 :     StructuredCloneReadInfo* readInfo = mCloneReadInfos.AppendElement();
     976              44 :     NS_ASSERTION(readInfo, "This shouldn't fail!");
     977                 : 
     978                 :     rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
     979              44 :       mDatabase->Manager(), *readInfo);
     980              44 :     NS_ENSURE_SUCCESS(rv, rv);
     981                 :   }
     982              12 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     983                 : 
     984              12 :   return NS_OK;
     985                 : }
     986                 : 
     987                 : nsresult
     988              12 : GetAllHelper::GetSuccessResult(JSContext* aCx,
     989                 :                                jsval* aVal)
     990                 : {
     991              12 :   NS_ASSERTION(mCloneReadInfos.Length() <= mLimit, "Too many results!");
     992                 : 
     993              12 :   nsresult rv = ConvertCloneReadInfosToArray(aCx, mCloneReadInfos, aVal);
     994                 : 
     995              12 :   for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
     996               0 :     mCloneReadInfos[index].mCloneBuffer.clear();
     997                 :   }
     998                 : 
     999              12 :   NS_ENSURE_SUCCESS(rv, rv);
    1000              12 :   return NS_OK;
    1001                 : }
    1002                 : 
    1003                 : nsresult
    1004              89 : OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
    1005                 : {
    1006              89 :   NS_ASSERTION(aConnection, "Passed a null connection!");
    1007                 : 
    1008             178 :   nsCString table;
    1009              89 :   if (mIndex->IsUnique()) {
    1010              31 :     table.AssignLiteral("unique_index_data");
    1011                 :   }
    1012                 :   else {
    1013              58 :     table.AssignLiteral("index_data");
    1014                 :   }
    1015                 : 
    1016             178 :   NS_NAMED_LITERAL_CSTRING(value, "value");
    1017                 : 
    1018             178 :   nsCString keyRangeClause;
    1019              89 :   if (mKeyRange) {
    1020              33 :     mKeyRange->GetBindingClause(value, keyRangeClause);
    1021                 :   }
    1022                 : 
    1023             178 :   nsCAutoString directionClause(" ORDER BY value ");
    1024              89 :   switch (mDirection) {
    1025                 :     case IDBCursor::NEXT:
    1026                 :     case IDBCursor::NEXT_UNIQUE:
    1027              86 :       directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
    1028              86 :       break;
    1029                 : 
    1030                 :     case IDBCursor::PREV:
    1031               2 :       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
    1032               2 :       break;
    1033                 : 
    1034                 :     case IDBCursor::PREV_UNIQUE:
    1035               1 :       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
    1036               1 :       break;
    1037                 : 
    1038                 :     default:
    1039               0 :       NS_NOTREACHED("Unknown direction!");
    1040                 :   }
    1041              89 :   nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
    1042              89 :                                             "FROM ") + table +
    1043             267 :                          NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
    1044              89 :                          keyRangeClause + directionClause +
    1045             356 :                          NS_LITERAL_CSTRING(" LIMIT 1");
    1046                 : 
    1047                 :   nsCOMPtr<mozIStorageStatement> stmt =
    1048             178 :     mTransaction->GetCachedStatement(firstQuery);
    1049              89 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1050                 : 
    1051             178 :   mozStorageStatementScoper scoper(stmt);
    1052                 : 
    1053             178 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
    1054              89 :                                       mIndex->Id());
    1055              89 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1056                 : 
    1057              89 :   if (mKeyRange) {
    1058              33 :     rv = mKeyRange->BindToStatement(stmt);
    1059              33 :     NS_ENSURE_SUCCESS(rv, rv);
    1060                 :   }
    1061                 : 
    1062                 :   bool hasResult;
    1063              89 :   rv = stmt->ExecuteStep(&hasResult);
    1064              89 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1065                 : 
    1066              89 :   if (!hasResult) {
    1067              15 :     mKey.Unset();
    1068              15 :     return NS_OK;
    1069                 :   }
    1070                 : 
    1071              74 :   rv = mKey.SetFromStatement(stmt, 0);
    1072              74 :   NS_ENSURE_SUCCESS(rv, rv);
    1073                 : 
    1074              74 :   rv = mObjectKey.SetFromStatement(stmt, 1);
    1075              74 :   NS_ENSURE_SUCCESS(rv, rv);
    1076                 : 
    1077                 :   // Now we need to make the query to get the next match.
    1078              74 :   nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
    1079              74 :                                                 " FROM ") + table +
    1080             296 :                              NS_LITERAL_CSTRING(" WHERE index_id = :id");
    1081                 : 
    1082             148 :   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
    1083                 : 
    1084              74 :   switch (mDirection) {
    1085                 :     case IDBCursor::NEXT:
    1086              70 :       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
    1087              21 :         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
    1088              21 :                               queryStart);
    1089              21 :         mRangeKey = mKeyRange->Upper();
    1090                 :       }
    1091                 :       mContinueQuery =
    1092                 :         queryStart +
    1093             140 :         NS_LITERAL_CSTRING(" AND value >= :current_key AND "
    1094                 :                            "( value > :current_key OR "
    1095                 :                            "  object_data_key > :object_key )") +
    1096              70 :         directionClause +
    1097             210 :         NS_LITERAL_CSTRING(" LIMIT ");
    1098                 :       mContinueToQuery =
    1099                 :         queryStart +
    1100             140 :         NS_LITERAL_CSTRING(" AND value >= :current_key ") +
    1101              70 :         directionClause +
    1102             210 :         NS_LITERAL_CSTRING(" LIMIT ");
    1103              70 :       break;
    1104                 : 
    1105                 :     case IDBCursor::NEXT_UNIQUE:
    1106               1 :       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
    1107               1 :         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
    1108               1 :                               queryStart);
    1109               1 :         mRangeKey = mKeyRange->Upper();
    1110                 :       }
    1111                 :       mContinueQuery =
    1112               2 :         queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
    1113               1 :         directionClause +
    1114               3 :         NS_LITERAL_CSTRING(" LIMIT ");
    1115                 :       mContinueToQuery =
    1116               2 :         queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
    1117               1 :         directionClause +
    1118               3 :         NS_LITERAL_CSTRING(" LIMIT ");
    1119               1 :       break;
    1120                 : 
    1121                 :     case IDBCursor::PREV:
    1122               2 :       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
    1123               0 :         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
    1124               0 :                               queryStart);
    1125               0 :         mRangeKey = mKeyRange->Lower();
    1126                 :       }
    1127                 : 
    1128                 :       mContinueQuery =
    1129                 :         queryStart +
    1130               4 :         NS_LITERAL_CSTRING(" AND value <= :current_key AND "
    1131                 :                            "( value < :current_key OR "
    1132                 :                            "  object_data_key < :object_key )") +
    1133               2 :         directionClause +
    1134               6 :         NS_LITERAL_CSTRING(" LIMIT ");
    1135                 :       mContinueToQuery =
    1136                 :         queryStart +
    1137               4 :         NS_LITERAL_CSTRING(" AND value <= :current_key ") +
    1138               2 :         directionClause +
    1139               6 :         NS_LITERAL_CSTRING(" LIMIT ");
    1140               2 :       break;
    1141                 : 
    1142                 :     case IDBCursor::PREV_UNIQUE:
    1143               1 :       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
    1144               0 :         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
    1145               0 :                               queryStart);
    1146               0 :         mRangeKey = mKeyRange->Lower();
    1147                 :       }
    1148                 :       mContinueQuery =
    1149                 :         queryStart +
    1150               2 :         NS_LITERAL_CSTRING(" AND value < :current_key") +
    1151               1 :         directionClause +
    1152               3 :         NS_LITERAL_CSTRING(" LIMIT ");
    1153                 :       mContinueToQuery =
    1154                 :         queryStart +
    1155               2 :         NS_LITERAL_CSTRING(" AND value <= :current_key") +
    1156               1 :         directionClause +
    1157               3 :         NS_LITERAL_CSTRING(" LIMIT ");
    1158               1 :       break;
    1159                 : 
    1160                 :     default:
    1161               0 :       NS_NOTREACHED("Unknown direction type!");
    1162                 :   }
    1163                 : 
    1164              74 :   return NS_OK;
    1165                 : }
    1166                 : 
    1167                 : nsresult
    1168              89 : OpenKeyCursorHelper::GetSuccessResult(JSContext* aCx,
    1169                 :                                       jsval* aVal)
    1170                 : {
    1171              89 :   if (mKey.IsUnset()) {
    1172              15 :     *aVal = JSVAL_VOID;
    1173              15 :     return NS_OK;
    1174                 :   }
    1175                 : 
    1176                 :   nsRefPtr<IDBCursor> cursor =
    1177                 :     IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
    1178             148 :                       mContinueQuery, mContinueToQuery, mKey, mObjectKey);
    1179              74 :   NS_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1180                 : 
    1181              74 :   return WrapNative(aCx, cursor, aVal);
    1182                 : }
    1183                 : 
    1184                 : nsresult
    1185              57 : OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
    1186                 : {
    1187              57 :   NS_ASSERTION(aConnection, "Passed a null connection!");
    1188                 : 
    1189             114 :   nsCString indexTable;
    1190              57 :   if (mIndex->IsUnique()) {
    1191              20 :     indexTable.AssignLiteral("unique_index_data");
    1192                 :   }
    1193                 :   else {
    1194              37 :     indexTable.AssignLiteral("index_data");
    1195                 :   }
    1196                 : 
    1197             114 :   NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
    1198                 : 
    1199             114 :   nsCString keyRangeClause;
    1200              57 :   if (mKeyRange) {
    1201              34 :     mKeyRange->GetBindingClause(value, keyRangeClause);
    1202                 :   }
    1203                 : 
    1204             114 :   nsCAutoString directionClause(" ORDER BY index_table.value ");
    1205              57 :   switch (mDirection) {
    1206                 :     case IDBCursor::NEXT:
    1207                 :     case IDBCursor::NEXT_UNIQUE:
    1208                 :       directionClause +=
    1209              53 :         NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
    1210              53 :       break;
    1211                 : 
    1212                 :     case IDBCursor::PREV:
    1213                 :       directionClause +=
    1214               3 :         NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
    1215               3 :       break;
    1216                 : 
    1217                 :     case IDBCursor::PREV_UNIQUE:
    1218                 :       directionClause +=
    1219               1 :         NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
    1220               1 :       break;
    1221                 : 
    1222                 :     default:
    1223               0 :       NS_NOTREACHED("Unknown direction!");
    1224                 :   }
    1225                 : 
    1226                 :   nsCString firstQuery =
    1227              57 :     NS_LITERAL_CSTRING("SELECT index_table.value, "
    1228                 :                        "index_table.object_data_key, object_data.data, "
    1229                 :                        "object_data.file_ids FROM ") +
    1230              57 :     indexTable +
    1231             171 :     NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
    1232                 :                        "index_table.object_data_id = object_data.id "
    1233                 :                        "WHERE index_table.index_id = :id") +
    1234              57 :     keyRangeClause + directionClause +
    1235             228 :     NS_LITERAL_CSTRING(" LIMIT 1");
    1236                 : 
    1237                 :   nsCOMPtr<mozIStorageStatement> stmt =
    1238             114 :     mTransaction->GetCachedStatement(firstQuery);
    1239              57 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1240                 : 
    1241             114 :   mozStorageStatementScoper scoper(stmt);
    1242                 : 
    1243              57 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
    1244              57 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1245                 : 
    1246              57 :   if (mKeyRange) {
    1247              34 :     rv = mKeyRange->BindToStatement(stmt);
    1248              34 :     NS_ENSURE_SUCCESS(rv, rv);
    1249                 :   }
    1250                 : 
    1251                 :   bool hasResult;
    1252              57 :   rv = stmt->ExecuteStep(&hasResult);
    1253              57 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1254                 : 
    1255              57 :   if (!hasResult) {
    1256               6 :     mKey.Unset();
    1257               6 :     return NS_OK;
    1258                 :   }
    1259                 : 
    1260              51 :   rv = mKey.SetFromStatement(stmt, 0);
    1261              51 :   NS_ENSURE_SUCCESS(rv, rv);
    1262                 : 
    1263              51 :   rv = mObjectKey.SetFromStatement(stmt, 1);
    1264              51 :   NS_ENSURE_SUCCESS(rv, rv);
    1265                 : 
    1266                 :   rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 2, 3,
    1267              51 :     mDatabase->Manager(), mCloneReadInfo);
    1268              51 :   NS_ENSURE_SUCCESS(rv, rv);
    1269                 : 
    1270                 :   // Now we need to make the query to get the next match.
    1271                 :   nsCAutoString queryStart =
    1272              51 :     NS_LITERAL_CSTRING("SELECT index_table.value, "
    1273                 :                        "index_table.object_data_key, object_data.data, "
    1274                 :                        "object_data.file_ids FROM ") +
    1275              51 :     indexTable +
    1276             204 :     NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
    1277                 :                        "index_table.object_data_id = object_data.id "
    1278                 :                        "WHERE index_table.index_id = :id");
    1279                 : 
    1280             102 :   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
    1281                 : 
    1282             102 :   NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
    1283                 : 
    1284              51 :   switch (mDirection) {
    1285                 :     case IDBCursor::NEXT:
    1286              46 :       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
    1287              24 :         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
    1288              24 :                               queryStart);
    1289              24 :         mRangeKey = mKeyRange->Upper();
    1290                 :       }
    1291                 :       mContinueQuery =
    1292                 :         queryStart +
    1293              92 :         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
    1294                 :                            "( index_table.value > :current_key OR "
    1295                 :                            "  index_table.object_data_key > :object_key ) ") +
    1296              46 :         directionClause + limit;
    1297                 :       mContinueToQuery =
    1298                 :         queryStart +
    1299              92 :         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
    1300              46 :         directionClause + limit;
    1301              46 :       break;
    1302                 : 
    1303                 :     case IDBCursor::NEXT_UNIQUE:
    1304               1 :       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
    1305               1 :         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
    1306               1 :                               queryStart);
    1307               1 :         mRangeKey = mKeyRange->Upper();
    1308                 :       }
    1309                 :       mContinueQuery =
    1310                 :         queryStart +
    1311               2 :         NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
    1312               1 :         directionClause + limit;
    1313                 :       mContinueToQuery =
    1314                 :         queryStart +
    1315               2 :         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
    1316               1 :         directionClause + limit;
    1317               1 :       break;
    1318                 : 
    1319                 :     case IDBCursor::PREV:
    1320               3 :       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
    1321               1 :         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
    1322               1 :                               queryStart);
    1323               1 :         mRangeKey = mKeyRange->Lower();
    1324                 :       }
    1325                 :       mContinueQuery =
    1326                 :         queryStart +
    1327               6 :         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
    1328                 :                            "( index_table.value < :current_key OR "
    1329                 :                            "  index_table.object_data_key < :object_key ) ") +
    1330               3 :         directionClause + limit;
    1331                 :       mContinueToQuery =
    1332                 :         queryStart +
    1333               6 :         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
    1334               3 :         directionClause + limit;
    1335               3 :       break;
    1336                 : 
    1337                 :     case IDBCursor::PREV_UNIQUE:
    1338               1 :       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
    1339               0 :         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
    1340               0 :                               queryStart);
    1341               0 :         mRangeKey = mKeyRange->Lower();
    1342                 :       }
    1343                 :       mContinueQuery =
    1344                 :         queryStart +
    1345               2 :         NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
    1346               1 :         directionClause + limit;
    1347                 :       mContinueToQuery =
    1348                 :         queryStart +
    1349               2 :         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
    1350               1 :         directionClause + limit;
    1351               1 :       break;
    1352                 : 
    1353                 :     default:
    1354               0 :       NS_NOTREACHED("Unknown direction type!");
    1355                 :   }
    1356                 : 
    1357              51 :   return NS_OK;
    1358                 : }
    1359                 : 
    1360                 : nsresult
    1361              57 : OpenCursorHelper::GetSuccessResult(JSContext* aCx,
    1362                 :                                    jsval* aVal)
    1363                 : {
    1364              57 :   if (mKey.IsUnset()) {
    1365               6 :     *aVal = JSVAL_VOID;
    1366               6 :     return NS_OK;
    1367                 :   }
    1368                 : 
    1369                 :   nsRefPtr<IDBCursor> cursor =
    1370                 :     IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
    1371                 :                       mContinueQuery, mContinueToQuery, mKey, mObjectKey,
    1372             102 :                       mCloneReadInfo);
    1373              51 :   NS_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1374                 : 
    1375              51 :   NS_ASSERTION(!mCloneReadInfo.mCloneBuffer.data(), "Should have swapped!");
    1376                 : 
    1377              51 :   return WrapNative(aCx, cursor, aVal);
    1378                 : }
    1379                 : 
    1380                 : nsresult
    1381              39 : CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
    1382                 : {
    1383              78 :   nsCString table;
    1384              39 :   if (mIndex->IsUnique()) {
    1385               8 :     table.AssignLiteral("unique_index_data");
    1386                 :   }
    1387                 :   else {
    1388              31 :     table.AssignLiteral("index_data");
    1389                 :   }
    1390                 : 
    1391              78 :   NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
    1392              78 :   NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
    1393              78 :   NS_NAMED_LITERAL_CSTRING(value, "value");
    1394                 : 
    1395              78 :   nsCAutoString keyRangeClause;
    1396              39 :   if (mKeyRange) {
    1397              22 :     if (!mKeyRange->Lower().IsUnset()) {
    1398                 :       AppendConditionClause(value, lowerKeyName, false,
    1399              16 :                             !mKeyRange->IsLowerOpen(), keyRangeClause);
    1400                 :     }
    1401              22 :     if (!mKeyRange->Upper().IsUnset()) {
    1402                 :       AppendConditionClause(value, upperKeyName, true,
    1403              15 :                             !mKeyRange->IsUpperOpen(), keyRangeClause);
    1404                 :     }
    1405                 :   }
    1406                 : 
    1407              78 :   nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
    1408             117 :                     NS_LITERAL_CSTRING(" WHERE index_id = :id") +
    1409              78 :                     keyRangeClause;
    1410                 : 
    1411              78 :   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
    1412              39 :   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1413                 : 
    1414              78 :   mozStorageStatementScoper scoper(stmt);
    1415                 : 
    1416              39 :   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
    1417              39 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1418                 : 
    1419              39 :   if (mKeyRange) {
    1420              22 :     if (!mKeyRange->Lower().IsUnset()) {
    1421              16 :       rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
    1422              16 :       NS_ENSURE_SUCCESS(rv, rv);
    1423                 :     }
    1424              22 :     if (!mKeyRange->Upper().IsUnset()) {
    1425              15 :       rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
    1426              15 :       NS_ENSURE_SUCCESS(rv, rv);
    1427                 :     }
    1428                 :   }
    1429                 : 
    1430                 :   bool hasResult;
    1431              39 :   rv = stmt->ExecuteStep(&hasResult);
    1432              39 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1433              39 :   NS_ENSURE_TRUE(hasResult, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    1434                 : 
    1435              39 :   mCount = stmt->AsInt64(0);
    1436              39 :   return NS_OK;
    1437                 : }
    1438                 : 
    1439                 : nsresult
    1440              39 : CountHelper::GetSuccessResult(JSContext* aCx,
    1441                 :                               jsval* aVal)
    1442                 : {
    1443              39 :   return JS_NewNumberValue(aCx, static_cast<double>(mCount), aVal);
    1444            4392 : }

Generated by: LCOV version 1.7