Backed out changeset d546bd2c46a4 (bug 490085) because it's broken (and thunderbird's test caught it)
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Wed, 17 Jun 2009 13:43:30 -0700
changeset 29305 83ba7296195e738749ce695f89d242ea98d4bcc6
parent 29300 d546bd2c46a4271215bbae1cbe87fdc6975afe21
child 29306 757078547b2283a555409d11654553d2953f7963
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs490085
milestone1.9.2a1pre
backs outd546bd2c46a4271215bbae1cbe87fdc6975afe21
Backed out changeset d546bd2c46a4 (bug 490085) because it's broken (and thunderbird's test caught it)
storage/public/Makefile.in
storage/public/mozIStorageBindingParams.idl
storage/public/mozIStorageBindingParamsArray.idl
storage/public/mozIStorageStatement.idl
storage/src/Makefile.in
storage/src/mozStorageAsyncStatementExecution.cpp
storage/src/mozStorageAsyncStatementExecution.h
storage/src/mozStorageBindingParams.cpp
storage/src/mozStorageBindingParams.h
storage/src/mozStorageBindingParamsArray.cpp
storage/src/mozStorageBindingParamsArray.h
storage/src/mozStorageConnection.cpp
storage/src/mozStorageStatement.cpp
storage/src/mozStorageStatement.h
storage/src/mozStorageStatementData.h
storage/test/unit/test_connection_executeAsync.js
storage/test/unit/test_statement_executeAsync.js
storage/test/unit/test_storage_statement_executeAsync.js
--- a/storage/public/Makefile.in
+++ b/storage/public/Makefile.in
@@ -57,18 +57,16 @@ XPIDLSRCS = \
 	mozIStorageStatement.idl \
 	mozIStorageStatementWrapper.idl \
 	mozIStorageValueArray.idl \
 	mozIStorageResultSet.idl \
 	mozIStorageRow.idl \
   mozIStorageError.idl \
   mozIStorageStatementCallback.idl \
   mozIStoragePendingStatement.idl \
-  mozIStorageBindingParamsArray.idl \
-  mozIStorageBindingParams.idl \
 	$(NULL)
 
 EXPORTS_NAMESPACES = mozilla
 
 EXPORTS = \
 	mozStorageHelper.h \
 	mozStorage.h \
 	$(NULL)
deleted file mode 100644
--- a/storage/public/mozIStorageBindingParams.idl
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 sts=2 et
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-interface nsIVariant;
-
-[scriptable, uuid(a8d4827c-641c-45e3-a9ea-493570b4106b)]
-interface mozIStorageBindingParams : nsISupports {
-  /**
-   * Binds aValue to the parameter with the name aName.
-   *
-   * @param aName
-   *        The name of the parameter to bind aValue to.
-   * @param aValue
-   *        The value to bind.
-   */
-   void bindByName(in AUTF8String aName,
-                   in nsIVariant aValue);
-   [noscript] void bindUTF8StringByName(in AUTF8String aName,
-                                        in AUTF8String aValue);
-   [noscript] void bindStringByName(in AUTF8String aName,
-                                    in AString aValue);
-   [noscript] void bindDoubleByName(in AUTF8String aName,
-                                    in double aValue);
-   [noscript] void bindInt32ByName(in AUTF8String aName,
-                                   in long aValue);
-   [noscript] void bindInt64ByName(in AUTF8String aName,
-                                   in long long aValue);
-   [noscript] void bindNullByName(in AUTF8String aName);
-   void bindBlobByName(in AUTF8String aName,
-                       [array, const, size_is(aValueSize)] in octet aValue,
-                       in unsigned long aValueSize);
-
-   /**
-    * Binds aValue to the parameter with the index aIndex.
-    *
-    * @param aIndex
-    *        The zero-based index of the parameter to bind aValue to.
-    * @param aValue
-    *        The value to bind.
-    */
-   void bindByIndex(in unsigned long aIndex,
-                    in nsIVariant aValue);
-   [noscript] void bindUTF8StringByIndex(in unsigned long aIndex,
-                                         in AUTF8String aValue);
-   [noscript] void bindStringByIndex(in unsigned long aIndex,
-                                     in AString aValue);
-   [noscript] void bindDoubleByIndex(in unsigned long aIndex,
-                                     in double aValue);
-   [noscript] void bindInt32ByIndex(in unsigned long aIndex,
-                                    in long aValue);
-   [noscript] void bindInt64ByIndex(in unsigned long aIndex,
-                                    in long long aValue);
-   [noscript] void bindNullByIndex(in unsigned long aIndex);
-   void bindBlobByIndex(in unsigned long aIndex,
-                        [array, const, size_is(aValueSize)] in octet aValue,
-                        in unsigned long aValueSize);
-};
deleted file mode 100644
--- a/storage/public/mozIStorageBindingParamsArray.idl
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 sts=2 et
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-interface mozIStorageBindingParams;
-
-[scriptable, uuid(e676e1a3-1dc6-4802-ac03-291fa9de7f93)]
-interface mozIStorageBindingParamsArray : nsISupports {
-  /**
-   * Creates a new mozIStorageBindingParams object that can be added to this
-   * array.
-   *
-   * @returns a mozIStorageBindingParams object that can be used to specify
-   *          parameters that need to be bound.
-   */
-  mozIStorageBindingParams newBindingParams();
-
-  /**
-   * Adds the parameters to the end of this array.
-   *
-   * @param aParameters
-   *        The parameters to add to this array.
-   */
-  void addParams(in mozIStorageBindingParams aParameters);
-};
--- a/storage/public/mozIStorageStatement.idl
+++ b/storage/public/mozIStorageStatement.idl
@@ -38,19 +38,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "mozIStorageValueArray.idl"
 
 interface mozIStorageConnection;
 interface mozIStorageStatementCallback;
 interface mozIStoragePendingStatement;
-interface mozIStorageBindingParamsArray;
 
-[scriptable, uuid(20c45bdd-51d4-4f07-b70e-5feaa6302197)]
+[scriptable, uuid(52d740cd-1c25-471f-a848-98d1a00a2963)]
 interface mozIStorageStatement : mozIStorageValueArray {
   /**
    * Finalizes a statement so you can successfully close a database connection.
    * This method does not need to be used from native callers since you can just
    * set the statement to null, but is extremely useful to JS callers.
    */
   void finalize();
 
@@ -126,34 +125,16 @@ interface mozIStorageStatement : mozISto
   void bindInt32Parameter(in unsigned long aParamIndex, in long aValue);
   void bindInt64Parameter(in unsigned long aParamIndex, in long long aValue);
   void bindNullParameter(in unsigned long aParamIndex);
   void bindBlobParameter(in unsigned long aParamIndex,
                          [array,const,size_is(aValueSize)] in octet aValue,
                          in unsigned long aValueSize);
 
   /**
-   * Binds the array of parameters to the statement.  When executeAsync is
-   * called, all the parameters in aParameters are bound and then executed.
-   *
-   * @param aParameters
-   *        The array of parameters to bind to the statement upon execution.
-   */
-  void bindParameters(in mozIStorageBindingParamsArray aParameters);
-
-  /**
-   * Creates a new mozIStorageBindingParamsArray that can be used to bind
-   * multiple sets of data to a statement.
-   *
-   * @returns a mozIStorageBindingParamsArray that multiple sets of parameters
-   *          can be bound to.
-   */
-  mozIStorageBindingParamsArray newBindingParamsArray();
-
-  /**
    * Execute the query, ignoring any results.  This is accomplished by
    * calling step() once, and then calling reset().
    *
    * Error and last insert info, etc. are available from
    * the mozStorageConnection.
    */
   void execute();
 
--- a/storage/src/Makefile.in
+++ b/storage/src/Makefile.in
@@ -78,18 +78,16 @@ CPPSRCS = \
   mozStorageArgValueArray.cpp \
   mozStorageSQLFunctions.cpp \
   mozStorageRow.cpp \
   mozStorageResultSet.cpp \
   mozStorageError.cpp \
   mozStorageAsyncStatementExecution.cpp \
   mozStorageStatementJSHelper.cpp \
   mozStoragePrivateHelpers.cpp \
-  mozStorageBindingParamsArray.cpp \
-  mozStorageBindingParams.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
 	$(SQLITE_CFLAGS)
 
 # This is the default value.  If we ever change it when compiling sqlite, we
 # will need to change it here as well.
 DEFINES += -DSQLITE_MAX_LIKE_PATTERN_LENGTH=50000
--- a/storage/src/mozStorageAsyncStatementExecution.cpp
+++ b/storage/src/mozStorageAsyncStatementExecution.cpp
@@ -38,24 +38,22 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAutoPtr.h"
 #include "prtime.h"
 
 #include "sqlite3.h"
 
 #include "mozIStorageStatementCallback.h"
-#include "mozStorageBindingParams.h"
 #include "mozStorageHelper.h"
 #include "mozStorageResultSet.h"
 #include "mozStorageRow.h"
 #include "mozStorageConnection.h"
 #include "mozStorageError.h"
 #include "mozStoragePrivateHelpers.h"
-#include "mozStorageStatementData.h"
 #include "mozStorageAsyncStatementExecution.h"
 
 namespace mozilla {
 namespace storage {
 
 /**
  * The following constants help batch rows into result sets.
  * MAX_MILLISECONDS_BETWEEN_RESULTS was chosen because any user-based task that
@@ -169,17 +167,17 @@ private:
 
 } // anonymous namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 //// AsyncExecuteStatements
 
 /* static */
 nsresult
-AsyncExecuteStatements::execute(StatementDataArray &aStatements,
+AsyncExecuteStatements::execute(sqlite3_stmt_array &aStatements,
                                 Connection *aConnection,
                                 mozIStorageStatementCallback *aCallback,
                                 mozIStoragePendingStatement **_stmt)
 {
   // Create our event to run in the background
   nsRefPtr<AsyncExecuteStatements> event =
     new AsyncExecuteStatements(aStatements, aConnection, aCallback);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
@@ -190,17 +188,17 @@ AsyncExecuteStatements::execute(Statemen
   nsresult rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Return it as the pending statement object
   NS_ADDREF(*_stmt = event);
   return NS_OK;
 }
 
-AsyncExecuteStatements::AsyncExecuteStatements(StatementDataArray &aStatements,
+AsyncExecuteStatements::AsyncExecuteStatements(sqlite3_stmt_array &aStatements,
                                                Connection *aConnection,
                                                mozIStorageStatementCallback *aCallback)
 : mConnection(aConnection)
 , mTransactionManager(nsnull)
 , mCallback(aCallback)
 , mCallingThread(::do_GetCurrentThread())
 , mMaxIntervalWait(::PR_MicrosecondsToInterval(MAX_MILLISECONDS_BETWEEN_RESULTS))
 , mIntervalStart(::PR_IntervalNow())
@@ -224,57 +222,16 @@ AsyncExecuteStatements::shouldNotify()
 
   // We do not need to acquire mMutex here because it can only ever be written
   // to on the calling thread, and the only thread that can call us is the
   // calling thread, so we know that our access is serialized.
   return !mCancelRequested;
 }
 
 bool
-AsyncExecuteStatements::bindExecuteAndProcessStatement(StatementData &aData,
-                                                       bool aLastStatement)
-{
-  mMutex.AssertNotCurrentThreadOwns();
-
-  sqlite3_stmt *stmt(aData);
-  BindingParamsArray *paramsArray(aData);
-
-  // Iterate through all of our parameters, bind them, and execute.
-  bool continueProcessing = true;
-  BindingParamsArray::iterator itr = paramsArray->begin();
-  BindingParamsArray::iterator end = paramsArray->end();
-  while (itr != end && continueProcessing) {
-    // Bind the data to our statement.
-    nsCOMPtr<mozIStorageError> error;
-    error = (*itr)->bind(stmt);
-    if (error) {
-      // Set our error state.
-      {
-        MutexAutoLock mutex(mMutex);
-        mState = ERROR;
-      }
-
-      // And notify.
-      (void)notifyError(error);
-      return false;
-    }
-
-    // Advance our iterator, execute, and then process the statement.
-    itr++;
-    bool lastStatement = aLastStatement && itr == end;
-    continueProcessing = executeAndProcessStatement(stmt, lastStatement);
-
-    // Always reset our statement.
-    (void)::sqlite3_reset(stmt);
-  }
-
-  return continueProcessing;
-}
-
-bool
 AsyncExecuteStatements::executeAndProcessStatement(sqlite3_stmt *aStatement,
                                                    bool aLastStatement)
 {
   mMutex.AssertNotCurrentThreadOwns();
 
   // We need to hold the mutex for statement execution so we can properly
   // reflect state in case we are canceled.  We release the mutex in a few areas
   // in order to allow for cancelation to occur.
@@ -415,18 +372,20 @@ AsyncExecuteStatements::notifyComplete()
 {
   mMutex.AssertNotCurrentThreadOwns();
   NS_ASSERTION(mState != PENDING,
                "Still in a pending state when calling Complete!");
 
   // Finalize our statements before we try to commit or rollback.  If we are
   // canceling and have statements that think they have pending work, the
   // rollback will fail.
-  for (PRUint32 i = 0; i < mStatements.Length(); i++)
-    mStatements[i].finalize();
+  for (PRUint32 i = 0; i < mStatements.Length(); i++) {
+    (void)::sqlite3_finalize(mStatements[i]);
+    mStatements[i] = NULL;
+  }
 
   // Handle our transaction, if we have one
   if (mTransactionManager) {
     if (mState == COMPLETED) {
       nsresult rv = mTransactionManager->Commit();
       if (NS_FAILED(rv)) {
         mState = ERROR;
         (void)notifyError(mozIStorageError::ERROR,
@@ -462,29 +421,18 @@ AsyncExecuteStatements::notifyError(PRIn
   mMutex.AssertNotCurrentThreadOwns();
 
   if (!mCallback)
     return NS_OK;
 
   nsCOMPtr<mozIStorageError> errorObj(new Error(aErrorCode, aMessage));
   NS_ENSURE_TRUE(errorObj, NS_ERROR_OUT_OF_MEMORY);
 
-  return notifyError(errorObj);
-}
-
-nsresult
-AsyncExecuteStatements::notifyError(mozIStorageError *aError)
-{
-  mMutex.AssertNotCurrentThreadOwns();
-
-  if (!mCallback)
-    return NS_OK;
-
   nsRefPtr<ErrorNotifier> notifier =
-    new ErrorNotifier(mCallback, aError, this);
+    new ErrorNotifier(mCallback, errorObj, this);
   NS_ENSURE_TRUE(notifier, NS_ERROR_OUT_OF_MEMORY);
 
   return mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 AsyncExecuteStatements::notifyResults()
 {
@@ -557,37 +505,27 @@ AsyncExecuteStatements::Run()
       mState = CANCELED;
   }
   if (cancelRequested)
     return notifyComplete();
 
   // If there is more than one statement, run it in a transaction.  We assume
   // that we have been given write statements since getting a batch of read
   // statements doesn't make a whole lot of sense.
-  // Additionally, if we have only one statement and it has parameters to be
-  // bound, we assume that the consumer would want a transaction as well.
-  if (mStatements.Length() > 1 || mStatements[0].hasParametersToBeBound()) {
+  if (mStatements.Length() > 1) {
     // We don't error if this failed because it's not terrible if it does.
     mTransactionManager = new mozStorageTransaction(mConnection, PR_FALSE,
                                                     mozIStorageConnection::TRANSACTION_IMMEDIATE);
   }
 
   // Execute each statement, giving the callback results if it returns any.
   for (PRUint32 i = 0; i < mStatements.Length(); i++) {
-    bool finished = (i == (mStatements.Length() - 1));
-
-    // If we have parameters to bind, bind them, execute, and process.
-    if (mStatements[i].hasParametersToBeBound()) {
-      if (!bindExecuteAndProcessStatement(mStatements[i], finished))
-        break;
-    }
-    // Otherwise, just execute and process the statement.
-    else if (!executeAndProcessStatement(mStatements[i], finished)) {
+    PRBool finished = (i == (mStatements.Length() - 1));
+    if (!executeAndProcessStatement(mStatements[i], finished))
       break;
-    }
   }
 
   // If we still have results that we haven't notified about, take care of
   // them now.
   if (mResultSet)
     (void)notifyResults();
 
   // Notify about completion
--- a/storage/src/mozStorageAsyncStatementExecution.h
+++ b/storage/src/mozStorageAsyncStatementExecution.h
@@ -52,17 +52,16 @@
 struct sqlite3_stmt;
 class mozStorageTransaction;
 
 namespace mozilla {
 namespace storage {
 
 class Connection;
 class ResultSet;
-class StatementData;
 
 class AsyncExecuteStatements : public nsIRunnable
                              , public mozIStoragePendingStatement
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_MOZISTORAGEPENDINGSTATEMENT
@@ -72,69 +71,52 @@ public:
    */
   enum ExecutionState {
     PENDING = -1,
     COMPLETED = mozIStorageStatementCallback::REASON_FINISHED,
     CANCELED = mozIStorageStatementCallback::REASON_CANCELED,
     ERROR = mozIStorageStatementCallback::REASON_ERROR
   };
 
-  typedef nsTArray<StatementData> StatementDataArray;
+  typedef nsTArray<sqlite3_stmt *> sqlite3_stmt_array;
 
   /**
    * Executes a statement in the background, and passes results back to the
    * caller.
    *
    * @param aStatements
-   *        The statements to execute and possibly bind in the background.
-   *        Ownership is transfered from the caller.
+   *        The SQLite statements to execute in the background.  Ownership is
+   *        transfered from the caller.
    * @param aConnection
    *        The connection that created the statements to execute.
    * @param aCallback
    *        The callback that is notified of results, completion, and errors.
    * @param _stmt
    *        The handle to control the execution of the statements.
    */
-  static nsresult execute(StatementDataArray &aStatements,
+  static nsresult execute(sqlite3_stmt_array &aStatements,
                           Connection *aConnection,
                           mozIStorageStatementCallback *aCallback,
                           mozIStoragePendingStatement **_stmt);
 
   /**
    * Indicates when events on the calling thread should run or not.  Certain
    * events posted back to the calling thread should call this see if they
    * should run or not.
    *
    * @returns true if the event should notify still, false otherwise.
    */
   bool shouldNotify();
 
 private:
-  AsyncExecuteStatements(StatementDataArray &aStatements,
+  AsyncExecuteStatements(sqlite3_stmt_array &aStatements,
                          Connection *aConnection,
                          mozIStorageStatementCallback *aCallback);
 
   /**
-   * Binds and then executes a given statement until completion, an error
-   * occurs, or we are canceled.  If aLastStatement is true, we should set
-   * mState accordingly.
-   *
-   * @pre mMutex is not held
-   *
-   * @param aData
-   *        The StatementData to bind, execute, and then process.
-   * @param aLastStatement
-   *        Indicates if this is the last statement or not.  If it is, we have
-   *        to set the proper state.
-   * @returns true if we should continue to process statements, false otherwise.
-   */
-  bool bindExecuteAndProcessStatement(StatementData &aData,
-                                      bool aLastStatement);
-
-  /**
    * Executes a given statement until completion, an error occurs, or we are
    * canceled.  If aLastStatement is true, we should set mState accordingly.
    *
    * @pre mMutex is not held
    *
    * @param aStatement
    *        The statement to execute and then process.
    * @param aLastStatement
@@ -178,30 +160,27 @@ private:
    * Notifies callback about an error.
    *
    * @pre mMutex is not held
    *
    * @param aErrorCode
    *        The error code defined in mozIStorageError for the error.
    * @param aMessage
    *        The error string, if any.
-   * @param aError
-   *        The error object to notify the caller with.
    */
   nsresult notifyError(PRInt32 aErrorCode, const char *aMessage);
-  nsresult notifyError(mozIStorageError *aError);
 
   /**
    * Notifies the callback about a result set.
    *
    * @pre mMutex is not held
    */
   nsresult notifyResults();
 
-  StatementDataArray mStatements;
+  sqlite3_stmt_array mStatements;
   nsRefPtr<Connection> mConnection;
   mozStorageTransaction *mTransactionManager;
   mozIStorageStatementCallback *mCallback;
   nsCOMPtr<nsIThread> mCallingThread;
   nsRefPtr<ResultSet> mResultSet;
 
   /**
    * The maximum amount of time we want to wait between results.  Defined by
deleted file mode 100644
--- a/storage/src/mozStorageBindingParams.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include <limits.h>
-
-#include "nsString.h"
-
-#include "mozStorageError.h"
-#include "mozStoragePrivateHelpers.h"
-#include "mozStorageBindingParams.h"
-#include "mozStorageBindingParamsArray.h"
-#include "Variant.h"
-
-namespace mozilla {
-namespace storage {
-
-////////////////////////////////////////////////////////////////////////////////
-//// Local Helper Objects
-
-namespace {
-
-struct BindingColumnData
-{
-  BindingColumnData(sqlite3_stmt *aStmt,
-                    int aColumn)
-  : stmt(aStmt)
-  , column(aColumn)
-  {
-  }
-  sqlite3_stmt *stmt;
-  int column;
-};
-
-} // anonymous namespace
-
-////////////////////////////////////////////////////////////////////////////////
-//// sqlite3_stmt Specialization Functions (varaintToSQLite3T)
-
-template < >
-int
-sqlite3_T_int(BindingColumnData aData,
-              int aValue)
-{
-  return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
-}
-
-template < >
-int
-sqlite3_T_int64(BindingColumnData aData,
-                sqlite3_int64 aValue)
-{
-  return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
-}
-
-template < >
-int
-sqlite3_T_double(BindingColumnData aData,
-                 double aValue)
-{
-  return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
-}
-
-template < >
-int
-sqlite3_T_text16(BindingColumnData aData,
-                 nsString aValue)
-{
-  return ::sqlite3_bind_text16(aData.stmt,
-                               aData.column + 1,
-                               PromiseFlatString(aValue).get(),
-                               aValue.Length() * 2, // Length in bytes!
-                               SQLITE_TRANSIENT);
-}
-
-template < >
-int
-sqlite3_T_null(BindingColumnData aData)
-{
-  return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
-}
-
-template < >
-int
-sqlite3_T_blob(BindingColumnData aData,
-               const void *aBlob,
-               int aSize)
-{
-  return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
-                             NS_Free);
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// BindingParams
-
-BindingParams::BindingParams(BindingParamsArray *aOwningArray,
-                             Statement *aOwningStatement)
-: mOwningArray(aOwningArray)
-, mOwningStatement(aOwningStatement)
-, mLocked(false)
-{
-  (void)mOwningStatement->GetParameterCount(&mParamCount);
-}
-
-void
-BindingParams::lock()
-{
-  NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
-  mLocked = true;
-
-  // We no longer need to hold a reference to our statement or our owning array.
-  // The array owns us at this point, and it will own a reference to the
-  // statement.
-  mOwningStatement = nsnull;
-  mOwningArray = nsnull;
-}
-
-const BindingParamsArray *
-BindingParams::getOwner() const
-{
-  return mOwningArray;
-}
-
-already_AddRefed<mozIStorageError>
-BindingParams::bind(sqlite3_stmt *aStatement)
-{
-  // Iterate through all of our stored data, and bind it.
-  for (PRInt32 i = 0; i < mParameters.Count(); i++) {
-    int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
-    if (rc != SQLITE_OK) {
-      // We had an error while trying to bind.  Now we need to create an error
-      // object with the right message.  Note that we special case
-      // SQLITE_MISMATCH, but otherwise get the message from SQLite.
-      const char *msg = "Could not covert nsIVariant to SQLite type.";
-      if (rc != SQLITE_MISMATCH)
-        msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
-
-      nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
-      return err.forget();
-    }
-  }
-
-  // No error occurred, so return null!
-  return nsnull;
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(
-  BindingParams,
-  mozIStorageBindingParams
-)
-
-///////////////////////////////////////////////////////////////////////////////
-//// mozIStorageBindingParams
-
-NS_IMETHODIMP
-BindingParams::BindByName(const nsACString &aName,
-                          nsIVariant *aValue)
-{
-  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
-
-  // Get the column index that we need to store this at.
-  PRUint32 index;
-  nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return BindByIndex(index, aValue);
-}
-
-NS_IMETHODIMP
-BindingParams::BindUTF8StringByName(const nsACString &aName,
-                                    const nsACString &aValue)
-{
-  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindStringByName(const nsACString &aName,
-                                const nsAString &aValue)
-{
-  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindDoubleByName(const nsACString &aName,
-                                double aValue)
-{
-  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindInt32ByName(const nsACString &aName,
-                               PRInt32 aValue)
-{
-  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindInt64ByName(const nsACString &aName,
-                               PRInt64 aValue)
-{
-  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindNullByName(const nsACString &aName)
-{
-  nsCOMPtr<nsIVariant> value(new NullVariant());
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindBlobByName(const nsACString &aName,
-                              const PRUint8 *aValue,
-                              PRUint32 aValueSize)
-{
-  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
-  std::pair<const void *, int> data(
-    static_cast<const void *>(aValue),
-    int(aValueSize)
-  );
-  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByName(aName, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindByIndex(PRUint32 aIndex,
-                           nsIVariant *aValue)
-{
-  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
-  ENSURE_INDEX_VALUE(aIndex, mParamCount);
-
-  // Store the variant for later use.
-  NS_ENSURE_TRUE(mParameters.InsertObjectAt(aValue, aIndex),
-                 NS_ERROR_OUT_OF_MEMORY);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BindingParams::BindUTF8StringByIndex(PRUint32 aIndex,
-                                     const nsACString &aValue)
-{
-  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindStringByIndex(PRUint32 aIndex,
-                                 const nsAString &aValue)
-{
-  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindDoubleByIndex(PRUint32 aIndex,
-                                 double aValue)
-{
-  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindInt32ByIndex(PRUint32 aIndex,
-                                PRInt32 aValue)
-{
-  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindInt64ByIndex(PRUint32 aIndex,
-                                PRInt64 aValue)
-{
-  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindNullByIndex(PRUint32 aIndex)
-{
-  nsCOMPtr<nsIVariant> value(new NullVariant());
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-NS_IMETHODIMP
-BindingParams::BindBlobByIndex(PRUint32 aIndex,
-                               const PRUint8 *aValue,
-                               PRUint32 aValueSize)
-{
-  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
-  std::pair<const void *, int> data(
-    static_cast<const void *>(aValue),
-    int(aValueSize)
-  );
-  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
-  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
-
-  return BindByIndex(aIndex, value);
-}
-
-} // namespace storage
-} // namespace mozilla
deleted file mode 100644
--- a/storage/src/mozStorageBindingParams.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _mozStorageBindingParams_h_
-#define _mozStorageBindingParams_h_
-
-#include "nsAutoPtr.h"
-#include "nsCOMArray.h"
-#include "nsIVariant.h"
-
-#include "mozStorageBindingParamsArray.h"
-#include "mozStorageStatement.h"
-#include "mozIStorageBindingParams.h"
-
-class mozIStorageError;
-struct sqlite3_stmt;
-
-namespace mozilla {
-namespace storage {
-
-class BindingParams : public mozIStorageBindingParams
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_MOZISTORAGEBINDINGPARAMS
-
-  /**
-   * Locks the parameters and prevents further modification to it (such as
-   * binding more elements to it).
-   */
-  void lock();
-
-  /**
-   * @returns the pointer to the owning BindingParamsArray.
-   */
-  const BindingParamsArray *getOwner() const;
-
-  /**
-   * Binds our stored data to the statement.
-   *
-   * @param aStatement
-   *        The statement to bind our data to.
-   * @returns nsnull on success, or a mozIStorageError object if an error
-   *          occurred.
-   */
-  already_AddRefed<mozIStorageError> bind(sqlite3_stmt *aStatement);
-
-  BindingParams(BindingParamsArray *aOwningArray,
-                Statement *aOwningStatement);
-
-private:
-  nsRefPtr<BindingParamsArray> mOwningArray;
-  Statement *mOwningStatement;
-  nsCOMArray<nsIVariant> mParameters;
-  PRUint32 mParamCount;
-  bool mLocked;
-};
-
-} // namespace storage
-} // namespace mozilla
-
-#endif // _mozStorageBindingParams_h_
deleted file mode 100644
--- a/storage/src/mozStorageBindingParamsArray.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "mozStorageBindingParamsArray.h"
-#include "mozStorageBindingParams.h"
-
-namespace mozilla {
-namespace storage {
-
-////////////////////////////////////////////////////////////////////////////////
-//// BindingParamsArray
-
-BindingParamsArray::BindingParamsArray(Statement *aOwningStatement)
-: mOwningStatement(aOwningStatement)
-, mLocked(false)
-{
-}
-
-void
-BindingParamsArray::lock()
-{
-  NS_ASSERTION(mLocked == false, "Array has already been locked!");
-  mLocked = true;
-
-  // We also no longer need to hold a reference to our statement since it owns
-  // us.
-  mOwningStatement = nsnull;
-}
-
-const Statement *
-BindingParamsArray::getOwner() const
-{
-  return mOwningStatement;
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(
-  BindingParamsArray,
-  mozIStorageBindingParamsArray
-)
-
-///////////////////////////////////////////////////////////////////////////////
-//// mozIStorageBindingParamsArray
-
-NS_IMETHODIMP
-BindingParamsArray::NewBindingParams(mozIStorageBindingParams **_params)
-{
-  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
-
-  nsCOMPtr<mozIStorageBindingParams> params =
-    new BindingParams(this, mOwningStatement);
-  NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
-
-  params.forget(_params);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BindingParamsArray::AddParams(mozIStorageBindingParams *aParameters)
-{
-  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
-
-  BindingParams *params = static_cast<BindingParams *>(aParameters);
-
-  // Check to make sure that this set of parameters was created with us.
-  if (params->getOwner() != this)
-    return NS_ERROR_UNEXPECTED;
-
-  NS_ENSURE_TRUE(mArray.AppendElement(params), NS_ERROR_OUT_OF_MEMORY);
-
-  // Lock the parameters only after we've successfully added them.
-  params->lock();
-
-  return NS_OK;
-}
-
-} // namespace storage
-} // namespace mozilla
deleted file mode 100644
--- a/storage/src/mozStorageBindingParamsArray.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _mozStorageBindingParamsArray_h_
-#define _mozStorageBindingParamsArray_h_
-
-#include "nsAutoPtr.h"
-#include "nsTArray.h"
-
-#include "mozIStorageBindingParamsArray.h"
-
-namespace mozilla {
-namespace storage {
-
-class BindingParams;
-class Statement;
-
-class BindingParamsArray : public mozIStorageBindingParamsArray
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_MOZISTORAGEBINDINGPARAMSARRAY
-
-  BindingParamsArray(Statement *aOwningStatement);
-
-  /**
-   * Locks the array and prevents further modification to it (such as adding
-   * more elements to it).
-   */
-  void lock();
-
-  /**
-   * @returns the pointer to the owning BindingParamsArray.
-   */
-  const Statement *getOwner() const;
-
-  class iterator {
-  public:
-    iterator(BindingParamsArray *aArray,
-             PRUint32 aIndex)
-    : mArray(aArray)
-    , mIndex(aIndex)
-    {
-    }
-
-    iterator &operator++(int)
-    {
-      mIndex++;
-      return *this;
-    }
-
-    bool operator==(const iterator &aOther) const
-    {
-      return mIndex == aOther.mIndex;
-    }
-    bool operator!=(const iterator &aOther) const
-    {
-      return !(*this == aOther);
-    }
-    BindingParams *operator*()
-    {
-      NS_ASSERTION(mIndex < mArray->mArray.Length(),
-                   "Dereferenceing an invalid value!");
-      return mArray->mArray[mIndex].get();
-    }
-  private:
-    void operator--() { }
-    BindingParamsArray *mArray;
-    PRUint32 mIndex;
-  };
-
-  /**
-   * Obtains an iterator pointing to the beginning of the array.
-   */
-  inline iterator begin()
-  {
-    NS_ASSERTION(mLocked, "Obtaining an iterator when we are not locked!");
-    return iterator(this, 0);
-  }
-
-  /**
-   * Obtains an iterator pointing to the end of the array.
-   */
-  inline iterator end()
-  {
-    NS_ASSERTION(mLocked, "Obtaining an iterator when we are not locked!");
-    return iterator(this, mArray.Length());
-  }
-private:
-  nsRefPtr<Statement> mOwningStatement;
-  nsTArray< nsRefPtr<BindingParams> > mArray;
-  bool mLocked;
-
-  friend class iterator;
-};
-
-} // namespace storage
-} // namespace mozilla
-
-#endif // _mozStorageBindingParamsArray_h_
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -57,17 +57,16 @@
 
 #include "mozStorageAsyncStatementExecution.h"
 #include "mozStorageSQLFunctions.h"
 #include "mozStorageConnection.h"
 #include "mozStorageService.h"
 #include "mozStorageStatement.h"
 #include "mozStorageArgValueArray.h"
 #include "mozStoragePrivateHelpers.h"
-#include "mozStorageStatementData.h"
 
 #include "prlog.h"
 #include "prprf.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gStorageLog = nsnull;
 #endif
 
@@ -623,17 +622,17 @@ Connection::ExecuteSimpleSQL(const nsACS
 
 nsresult
 Connection::ExecuteAsync(mozIStorageStatement **aStatements,
                          PRUint32 aNumStatements,
                          mozIStorageStatementCallback *aCallback,
                          mozIStoragePendingStatement **_handle)
 {
   int rc = SQLITE_OK;
-  nsTArray<StatementData> stmts(aNumStatements);
+  nsTArray<sqlite3_stmt *> stmts(aNumStatements);
   for (PRUint32 i = 0; i < aNumStatements && rc == SQLITE_OK; i++) {
     sqlite3_stmt *old_stmt =
         static_cast<Statement *>(aStatements[i])->nativeStatement();
     if (!old_stmt) {
       rc = SQLITE_MISUSE;
       break;
     }
     NS_ASSERTION(::sqlite3_db_handle(old_stmt) == mDBConn,
@@ -653,19 +652,17 @@ Connection::ExecuteAsync(mozIStorageStat
            ("Cloned statement 0x%p to 0x%p", old_stmt, new_stmt));
 #endif
 
     // Transfer the bindings
     rc = sqlite3_transfer_bindings(old_stmt, new_stmt);
     if (rc != SQLITE_OK)
       break;
 
-    Statement *storageStmt = static_cast<Statement *>(aStatements[i]);
-    StatementData data(new_stmt, storageStmt->bindingParamsArray());
-    if (!stmts.AppendElement(data)) {
+    if (!stmts.AppendElement(new_stmt)) {
       rc = SQLITE_NOMEM;
       break;
     }
   }
 
   // Dispatch to the background
   nsresult rv = NS_OK;
   if (rc == SQLITE_OK)
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -501,43 +501,16 @@ Statement::BindBlobParameter(PRUint32 aP
     return NS_ERROR_NOT_INITIALIZED;
 
   int srv = ::sqlite3_bind_blob(mDBStatement, aParamIndex + 1, aValue,
                                 aValueSize, SQLITE_TRANSIENT);
   return convertResultCode(srv);
 }
 
 NS_IMETHODIMP
-Statement::BindParameters(mozIStorageBindingParamsArray *aParameters)
-{
-  if (!mDBStatement)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  BindingParamsArray *array = static_cast<BindingParamsArray *>(aParameters);
-  if (array->getOwner() != this)
-    return NS_ERROR_UNEXPECTED;
-
-  mParamsArray = array;
-  mParamsArray->lock();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Statement::NewBindingParamsArray(mozIStorageBindingParamsArray **_array)
-{
-  nsCOMPtr<mozIStorageBindingParamsArray> array =
-    new BindingParamsArray(this);
-  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
-
-  array.forget(_array);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 Statement::Execute()
 {
   if (!mDBStatement)
     return NS_ERROR_NOT_INITIALIZED;
 
   PRBool ret;
   nsresult rv = ExecuteStep(&ret);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/storage/src/mozStorageStatement.h
+++ b/storage/src/mozStorageStatement.h
@@ -40,17 +40,16 @@
 #ifndef _mozStorageStatement_h_
 #define _mozStorageStatement_h_
 
 #include "nsAutoPtr.h"
 #include "nsString.h"
 
 #include "nsTArray.h"
 
-#include "mozStorageBindingParamsArray.h"
 #include "mozIStorageStatement.h"
 
 class nsIXPConnectJSObjectHolder;
 struct sqlite3_stmt;
 
 namespace mozilla {
 namespace storage {
 class StatementJSHelper;
@@ -78,42 +77,27 @@ public:
                       const nsACString &aSQLStatement);
 
 
   /**
    * Obtains the native statement pointer.
    */
   inline sqlite3_stmt *nativeStatement() { return mDBStatement; }
 
-  /**
-   * Obtains and transfers ownership of the array of parameters that are bound
-   * to this statment.  This can be null.
-   */
-  inline already_AddRefed<BindingParamsArray> bindingParamsArray()
-  {
-    return mParamsArray.forget();
-  }
-
 private:
     ~Statement();
 
     nsRefPtr<Connection> mDBConnection;
     sqlite3_stmt *mDBStatement;
     PRUint32 mParamCount;
     PRUint32 mResultColumnCount;
     nsTArray<nsCString> mColumnNames;
     bool mExecuting;
 
     /**
-     * Holds the array of parameters to bind to this statement when we execute
-     * it asynchronously.
-     */
-    nsRefPtr<BindingParamsArray> mParamsArray;
-
-    /**
      * The following two members are only used with the JS helper.  They cache
      * the row and params objects.
      */
     nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementParamsHolder;
     nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementRowHolder;
 
     friend class StatementJSHelper;
 };
deleted file mode 100644
--- a/storage/src/mozStorageStatementData.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 sts=2 et
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _mozStorageStatementData_h_
-#define _mozStorageStatementData_h_
-
-#include "nsAutoPtr.h"
-#include "nsTArray.h"
-
-#include "mozStorageBindingParamsArray.h"
-
-struct sqlite3_stmt;
-
-namespace mozilla {
-namespace storage {
-
-class StatementData
-{
-public:
-  StatementData(sqlite3_stmt *aStatement,
-                already_AddRefed<BindingParamsArray> aParamsArray)
-  : mStatement(aStatement)
-  , mParamsArray(aParamsArray)
-  {
-  }
-  StatementData(const StatementData &aSource)
-  : mStatement(aSource.mStatement)
-  , mParamsArray(aSource.mParamsArray)
-  {
-  }
-  StatementData()
-  {
-  }
-
-  operator sqlite3_stmt *() const
-  {
-    NS_ASSERTION(mStatement, "NULL sqlite3_stmt being handed off!");
-    return mStatement;
-  }
-  operator BindingParamsArray *() const { return mParamsArray; }
-
-  /**
-   * Finalizes and NULLs out our sqlite3_stmt.  Also releases our parameter
-   * array since we'll no longer need it.
-   */
-  inline void finalize()
-  {
-    (void)::sqlite3_finalize(mStatement);
-    mStatement = NULL;
-    mParamsArray = nsnull;
-  }
-
-  /**
-   * Indicates if this statement has parameters to be bound before it is
-   * executed.
-   *
-   * @returns true if the statement has parameters to bind against, false
-   *          otherwise.
-   */
-  inline bool hasParametersToBeBound() const { return mParamsArray != nsnull; }
-
-private:
-  sqlite3_stmt *mStatement;
-  nsRefPtr<BindingParamsArray> mParamsArray;
-};
-
-} // namespace storage
-} // namespace mozilla
-
-#endif // _mozStorageStatementData_h_
--- a/storage/test/unit/test_connection_executeAsync.js
+++ b/storage/test/unit/test_connection_executeAsync.js
@@ -39,19 +39,21 @@
 
 const INTEGER = 1;
 const TEXT = "this is test text";
 const REAL = 3.23;
 const BLOB = [1, 2];
 
 function test_create_and_add()
 {
+  dump("test_create_and_add()\n");
+
   getOpenedDatabase().executeSimpleSQL(
     "CREATE TABLE test (" +
-      "id INTEGER, " +
+      "id INTEGER PRIMARY KEY, " +
       "string TEXT, " +
       "number REAL, " +
       "nuller NULL, " +
       "blober BLOB" +
     ")"
   );
 
   let stmts = [];
@@ -66,16 +68,17 @@ function test_create_and_add()
   stmts[1] = getOpenedDatabase().createStatement(
     "INSERT INTO test (string, number, nuller, blober) VALUES (?, ?, ?, ?)"
   );
   stmts[1].bindStringParameter(0, TEXT);
   stmts[1].bindDoubleParameter(1, REAL);
   stmts[1].bindNullParameter(2);
   stmts[1].bindBlobParameter(3, BLOB, BLOB.length);
 
+  do_test_pending();
   getOpenedDatabase().executeAsync(stmts, stmts.length, {
     handleResult: function(aResultSet)
     {
       dump("handleResult("+aResultSet+")\n");
       do_throw("unexpected results obtained!");
     },
     handleError: function(aError)
     {
@@ -115,153 +118,63 @@ function test_create_and_add()
       try {
         do_check_true(stmt.executeStep());
         do_check_eq(2, stmt.getInt32(0));
       }
       finally {
         stmt.finalize();
       }
 
-      // Run the next test.
-      run_next_test();
+      do_test_finished();
     }
   });
   stmts[0].finalize();
   stmts[1].finalize();
 }
 
 function test_transaction_created()
 {
+  dump("test_transaction_created()\n");
+
   let stmts = [];
   stmts[0] = getOpenedDatabase().createStatement(
     "BEGIN"
   );
   stmts[1] = getOpenedDatabase().createStatement(
     "SELECT * FROM test"
   );
 
+  do_test_pending()
   getOpenedDatabase().executeAsync(stmts, stmts.length, {
     handleResult: function(aResultSet)
     {
       dump("handleResults("+aResultSet+")\n");
       do_throw("unexpected results obtained!");
     },
     handleError: function(aError)
     {
       dump("handleError("+aError.result+")\n");
     },
     handleCompletion: function(aReason)
     {
       dump("handleCompletion("+aReason+")\n");
       do_check_eq(Ci.mozIStorageStatementCallback.REASON_ERROR, aReason);
-
-      // Run the next test.
-      run_next_test();
+      do_test_finished();
     }
   });
   stmts[0].finalize();
   stmts[1].finalize();
 }
 
-function test_multiple_bindings_on_statements()
-{
-  // This tests to make sure that we pass all the statements multiply bound
-  // parameters when we call executeAsync.
-  const AMOUNT_TO_ADD = 5;
-  const ITERATIONS = 5;
-
-  let stmts = [];
-  // We run the same statement twice, and should insert 2 * AMOUNT_TO_ADD.
-  for (let i = 0; i < ITERATIONS; i++) {
-    stmts[i] = getOpenedDatabase().createStatement(
-      "INSERT INTO test (id, string, number, nuller, blober) " +
-      "VALUES (:int, :text, :real, :null, :blob)"
-    );
-    let params = stmts[i].newBindingParamsArray()
-    for (let j = 0; j < AMOUNT_TO_ADD; j++) {
-      let bp = params.newBindingParams();
-      bp.bindByName("int", INTEGER);
-      bp.bindByName("text", TEXT);
-      bp.bindByName("real", REAL);
-      bp.bindByName("null", null);
-      bp.bindBlobByName("blob", BLOB, BLOB.length);
-      params.addParams(bp);
-    }
-    stmts[i].bindParameters(params);
-  }
-
-  // Get our current number of rows in the table.
-  let currentRows = 0;
-  let countStmt = getOpenedDatabase().createStatement(
-    "SELECT COUNT(1) AS count FROM test"
-  );
-  try {
-    do_check_true(countStmt.executeStep());
-    currentRows = countStmt.row.count;
-  }
-  finally {
-    countStmt.reset();
-  }
-
-  // Execute asynchronously.
-  getOpenedDatabase().executeAsync(stmts, stmts.length, {
-    handleResult: function(aResultSet)
-    {
-      do_throw("Unexpected call to handleResult!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("Unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_multiple_bindings_on_statements");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-
-      // Check to make sure we added all of our rows.
-      try {
-        do_check_true(countStmt.executeStep());
-        do_check_eq(currentRows + (ITERATIONS * AMOUNT_TO_ADD),
-                    countStmt.row.count);
-      }
-      finally {
-        countStmt.finalize();
-      }
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmts.forEach(function(stmt) stmt.finalize());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// Test Runner
 
 let tests =
 [
   test_create_and_add,
   test_transaction_created,
-  test_multiple_bindings_on_statements,
 ];
-let index = 0;
-
-function run_next_test()
-{
-  if (index < tests.length) {
-    do_test_pending();
-    print("Running the next test: " + tests[index].name);
-    tests[index++]();
-  }
-
-  do_test_finished();
-}
 
 function run_test()
 {
   cleanup();
 
-  do_test_pending();
-  run_next_test();
+  for (let i = 0; i < tests.length; i++)
+    tests[i]();
 }
deleted file mode 100644
--- a/storage/test/unit/test_statement_executeAsync.js
+++ /dev/null
@@ -1,1006 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Storage Test Code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// This file tests the functionality of mozIStorageStatement::executeAsync
-
-const INTEGER = 1;
-const TEXT = "this is test text";
-const REAL = 3.23;
-const BLOB = [1, 2];
-
-function test_create_table()
-{
-  // Ensure our table doesn't exists
-  do_check_false(getOpenedDatabase().tableExists("test"));
-
-  var stmt = getOpenedDatabase().createStatement(
-    "CREATE TABLE test (" +
-      "id INTEGER, " +
-      "string TEXT, " +
-      "number REAL, " +
-      "nuller NULL, " +
-      "blober BLOB" +
-    ")"
-  );
-
-  stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      dump("handleResult("+aResultSet+");\n");
-      do_throw("unexpected results obtained!");
-    },
-    handleError: function(aError)
-    {
-      print("error code " + aerror.result + " with message '" +
-            aerror.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason + ") for test_create_table");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-
-      // Check that the table has been created
-      do_check_true(getOpenedDatabase().tableExists("test"));
-
-      // Verify that it's created correctly (this will throw if it wasn't)
-      var stmt = getOpenedDatabase().createStatement(
-        "SELECT id, string, number, nuller, blober FROM test"
-      );
-      stmt.finalize();
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_add_data()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id, string, number, nuller, blober) " +
-    "VALUES (?, ?, ?, ?, ?)"
-  );
-  stmt.bindInt32Parameter(0, INTEGER);
-  stmt.bindStringParameter(1, TEXT);
-  stmt.bindDoubleParameter(2, REAL);
-  stmt.bindNullParameter(3);
-  stmt.bindBlobParameter(4, BLOB, BLOB.length);
-
-  stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      do_throw("unexpected results obtained!");
-    },
-    handleError: function(aError)
-    {
-      print("error code " + aerror.result + " with message '" +
-            aerror.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason + ") for test_add_data");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-
-      // Check that the result is in the table
-      var stmt = getOpenedDatabase().createStatement(
-        "SELECT string, number, nuller, blober FROM test WHERE id = ?"
-      );
-      stmt.bindInt32Parameter(0, INTEGER);
-      try {
-        do_check_true(stmt.executeStep());
-        do_check_eq(TEXT, stmt.getString(0));
-        do_check_eq(REAL, stmt.getDouble(1));
-        do_check_true(stmt.getIsNull(2));
-        var count = { value: 0 };
-        var blob = { value: null };
-        stmt.getBlob(3, count, blob);
-        do_check_eq(BLOB.length, count.value);
-        for (var i = 0; i < BLOB.length; i++)
-          do_check_eq(BLOB[i], blob.value[i]);
-      }
-      finally {
-        stmt.reset();
-        stmt.finalize();
-      }
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_get_data()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "SELECT string, number, nuller, blober, id FROM test WHERE id = ?"
-  );
-  stmt.bindInt32Parameter(0, 1);
-
-  stmt.executeAsync({
-    resultObtained: false,
-    handleResult: function(aResultSet)
-    {
-      dump("handleResult("+aResultSet+");\n");
-      do_check_false(this.resultObtained);
-      this.resultObtained = true;
-
-      // Check that we have a result
-      var tuple = aResultSet.getNextRow();
-      do_check_neq(null, tuple);
-
-      // Check that it's what we expect
-      do_check_eq(tuple.getResultByName("string"), tuple.getResultByIndex(0));
-      do_check_eq(TEXT, tuple.getResultByName("string"));
-      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_TEXT,
-                  tuple.getTypeOfIndex(0));
-
-      do_check_eq(tuple.getResultByName("number"), tuple.getResultByIndex(1));
-      do_check_eq(REAL, tuple.getResultByName("number"));
-      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT,
-                  tuple.getTypeOfIndex(1));
-
-      do_check_eq(tuple.getResultByName("nuller"), tuple.getResultByIndex(2));
-      do_check_eq(null, tuple.getResultByName("nuller"));
-      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_NULL,
-                  tuple.getTypeOfIndex(2));
-
-      var blobByName = tuple.getResultByName("blober");
-      do_check_eq(BLOB.length, blobByName.length);
-      var blobByIndex = tuple.getResultByIndex(3);
-      do_check_eq(BLOB.length, blobByIndex.length);
-      for (var i = 0; i < BLOB.length; i++) {
-        do_check_eq(BLOB[i], blobByName[i]);
-        do_check_eq(BLOB[i], blobByIndex[i]);
-      }
-      var count = { value: 0 };
-      var blob = { value: null };
-      tuple.getBlob(3, count, blob);
-      do_check_eq(BLOB.length, count.value);
-      for (var i = 0; i < BLOB.length; i++)
-        do_check_eq(BLOB[i], blob.value[i]);
-      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_BLOB,
-                  tuple.getTypeOfIndex(3));
-
-      do_check_eq(tuple.getResultByName("id"), tuple.getResultByIndex(4));
-      do_check_eq(INTEGER, tuple.getResultByName("id"));
-      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER,
-                  tuple.getTypeOfIndex(4));
-
-      // check that we have no more results
-      tuple = aResultSet.getNextRow();
-      do_check_eq(null, tuple);
-    },
-    handleError: function(aError)
-    {
-      print("error code " + aerror.result + " with message '" +
-            aerror.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason + ") for test_get_data");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-      do_check_true(this.resultObtained);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_tuple_out_of_bounds()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "SELECT string FROM test"
-  );
-
-  stmt.executeAsync({
-    resultObtained: false,
-    handleResult: function(aResultSet)
-    {
-      dump("handleResult("+aResultSet+");\n");
-      do_check_false(this.resultObtained);
-      this.resultObtained = true;
-
-      // Check that we have a result
-      var tuple = aResultSet.getNextRow();
-      do_check_neq(null, tuple);
-
-      // Check all out of bounds - should throw
-      var methods = [
-        "getTypeOfIndex",
-        "getInt32",
-        "getInt64",
-        "getDouble",
-        "getUTF8String",
-        "getString",
-        "getIsNull",
-      ];
-      for (var i in methods) {
-        try {
-          tuple[methods[i]](tuple.numEntries);
-          do_throw("did not throw :(");
-        }
-        catch (e) {
-          do_check_eq(Cr.NS_ERROR_ILLEGAL_VALUE, e.result);
-        }
-      }
-
-      // getBlob requires more args...
-      try {
-        var blob = { value: null };
-        var size = { value: 0 };
-        tuple.getBlob(tuple.numEntries, blob, size);
-        do_throw("did not throw :(");
-      }
-      catch (e) {
-        do_check_eq(Cr.NS_ERROR_ILLEGAL_VALUE, e.result);
-      }
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_tuple_out_of_bounds");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-      do_check_true(this.resultObtained);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_no_listener_works_on_success()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "DELETE FROM test WHERE id = ?"
-  );
-  stmt.bindInt32Parameter(0, 0);
-  stmt.executeAsync();
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_no_listener_works_on_results()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "SELECT ?"
-  );
-  stmt.bindInt32Parameter(0, 1);
-  stmt.executeAsync();
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_no_listener_works_on_error()
-{
-  // commit without a transaction will trigger an error
-  var stmt = getOpenedDatabase().createStatement(
-    "COMMIT"
-  );
-  stmt.executeAsync();
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_partial_listener_works()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "DELETE FROM test WHERE id = ?"
-  );
-  stmt.bindInt32Parameter(0, 0);
-  stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-    }
-  });
-  stmt.executeAsync({
-    handleError: function(aError)
-    {
-    }
-  });
-  stmt.executeAsync({
-    handleCompletion: function(aReason)
-    {
-    }
-  });
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_immediate_cancellation()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "DELETE FROM test WHERE id = ?"
-  );
-  stmt.bindInt32Parameter(0, 0);
-  let reason = Ci.mozIStorageStatementCallback.REASON_CANCELED;
-  var pendingStatement = stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      do_throw("unexpected result!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_immediate_cancellation");
-      do_check_eq(reason, aReason);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-
-  // Cancel immediately
-  if (!pendingStatement.cancel()) {
-    // It is possible that we finished before we canceled
-    reason = Ci.mozIStorageStatementCallback.REASON_FINISHED;
-  }
-
-  stmt.finalize();
-}
-
-function test_double_cancellation()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "DELETE FROM test WHERE id = ?"
-  );
-  stmt.bindInt32Parameter(0, 0);
-  let reason = Ci.mozIStorageStatementCallback.REASON_CANCELED;
-  var pendingStatement = stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      do_throw("unexpected result!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_double_cancellation");
-      do_check_eq(reason, aReason);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-
-  // Cancel immediately
-  if (!pendingStatement.cancel()) {
-    // It is possible that we finished before we canceled
-    reason = Ci.mozIStorageStatementCallback.REASON_FINISHED;
-  }
-
-  // And cancel again - expect an exception
-  try {
-    pendingStatement.cancel();
-    do_throw("function call should have thrown!");
-  }
-  catch (e) {
-    do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
-  }
-
-  stmt.finalize();
-}
-
-function test_double_execute()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "SELECT * FROM test"
-  );
-
-  var listener = {
-    _timesCompleted: 0,
-    _hasResults: false,
-    handleResult: function(aResultSet)
-    {
-      do_check_false(this._hasResults);
-      this._hasResults = true;
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_double_execute (iteration " +
-            (this._timesCompleted + 1) + ")");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-      do_check_true(this._hasResults);
-      this._hasResults = false;
-      this._timesCompleted++;
-
-      // Run the next test.
-      if (this._timesCompleted == 2)
-        run_next_test();
-    }
-  }
-  stmt.executeAsync(listener);
-  stmt.executeAsync(listener);
-  stmt.finalize();
-}
-
-function test_finalized_statement_does_not_crash()
-{
-  var stmt = getOpenedDatabase().createStatement(
-    "SELECT * FROM TEST"
-  );
-  stmt.finalize();
-  // we are concerned about a crash here; an error is fine.
-  try {
-    stmt.executeAsync();
-  }
-  catch (ex) {}
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_bind_multiple_rows_by_index()
-{
-  const AMOUNT_TO_ADD = 5;
-  var stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id, string, number, nuller, blober) " +
-    "VALUES (?, ?, ?, ?, ?)"
-  );
-  var array = stmt.newBindingParamsArray();
-  for (let i = 0; i < AMOUNT_TO_ADD; i++) {
-    let bp = array.newBindingParams();
-    bp.bindByIndex(0, INTEGER);
-    bp.bindByIndex(1, TEXT);
-    bp.bindByIndex(2, REAL);
-    bp.bindByIndex(3, null);
-    bp.bindBlobByIndex(4, BLOB, BLOB.length);
-    array.addParams(bp);
-  }
-  stmt.bindParameters(array);
-
-  // Get our current number of rows in the table.
-  var currentRows = 0;
-  var countStmt = getOpenedDatabase().createStatement(
-    "SELECT COUNT(1) AS count FROM test"
-  );
-  try {
-    do_check_true(countStmt.executeStep());
-    currentRows = countStmt.row.count;
-    print("We have " + currentRows + " rows in test_bind_multiple_rows_by_index");
-  }
-  finally {
-    countStmt.reset();
-  }
-
-  // Execute asynchronously.
-  stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      do_throw("Unexpected call to handleResult!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_bind_multiple_rows_by_index");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-
-      // Check to make sure we added all of our rows.
-      try {
-        do_check_true(countStmt.executeStep());
-        print("We now have " + currentRows +
-              " rows in test_bind_multiple_rows_by_index");
-        do_check_eq(currentRows + AMOUNT_TO_ADD, countStmt.row.count);
-      }
-      finally {
-        countStmt.finalize();
-      }
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_bind_multiple_rows_by_name()
-{
-  const AMOUNT_TO_ADD = 5;
-  var stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id, string, number, nuller, blober) " +
-    "VALUES (:int, :text, :real, :null, :blob)"
-  );
-  var array = stmt.newBindingParamsArray();
-  for (let i = 0; i < AMOUNT_TO_ADD; i++) {
-    let bp = array.newBindingParams();
-    bp.bindByName("int", INTEGER);
-    bp.bindByName("text", TEXT);
-    bp.bindByName("real", REAL);
-    bp.bindByName("null", null);
-    bp.bindBlobByName("blob", BLOB, BLOB.length);
-    array.addParams(bp);
-  }
-  stmt.bindParameters(array);
-
-  // Get our current number of rows in the table.
-  var currentRows = 0;
-  var countStmt = getOpenedDatabase().createStatement(
-    "SELECT COUNT(1) AS count FROM test"
-  );
-  try {
-    do_check_true(countStmt.executeStep());
-    currentRows = countStmt.row.count;
-    print("We have " + currentRows + " rows in test_bind_multiple_rows_by_name");
-  }
-  finally {
-    countStmt.reset();
-  }
-
-  // Execute asynchronously.
-  stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-      do_throw("Unexpected call to handleResult!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      do_throw("unexpected error!");
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_bind_multiple_rows_by_name");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
-
-      // Check to make sure we added all of our rows.
-      try {
-        do_check_true(countStmt.executeStep());
-        print("We now have " + currentRows +
-              " rows in test_bind_multiple_rows_by_name");
-        do_check_eq(currentRows + AMOUNT_TO_ADD, countStmt.row.count);
-      }
-      finally {
-        countStmt.finalize();
-      }
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_bind_out_of_bounds()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (?)"
-  );
-
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-
-  // Check variant binding.
-  let exceptionCaught = false;
-  try {
-    bp.bindByIndex(1, INTEGER);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Check blob binding.
-  exceptionCaught = false;
-  try {
-    bp.bindBlobByIndex(1, BLOB, BLOB.length);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_bind_no_such_name()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:foo)"
-  );
-
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-
-  // Check variant binding.
-  let exceptionCaught = false;
-  try {
-    bp.bindByName("doesnotexist", INTEGER);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Check blob binding.
-  exceptionCaught = false;
-  try {
-    bp.bindBlobByName("doesnotexist", BLOB, BLOB.length);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  stmt.finalize();
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_bind_bogus_type_by_index()
-{
-  // We try to bind a JS Object here that should fail to bind.
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (blober) " +
-    "VALUES (?)"
-  );
-
-  // We get an error after calling executeAsync, not when we bind.
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-  bp.bindByIndex(0, run_test);
-  array.addParams(bp);
-  stmt.bindParameters(array);
-
-  stmt.executeAsync({
-    _errorObtained: false,
-    handleResult: function(aResultSet)
-    {
-      do_throw("Unexpected call to handleResult!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      this._errorObtained = true;
-      do_check_eq(aError.result, Ci.mozIStorageError.MISMATCH);
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_bind_bogus_type_by_index");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_ERROR, aReason);
-      do_check_true(this._errorObtained);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_bind_bogus_type_by_name()
-{
-  // We try to bind a JS Object here that should fail to bind.
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (blober) " +
-    "VALUES (:blob)"
-  );
-
-  // We get an error after calling executeAsync, not when we bind.
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-  bp.bindByName("blob", run_test);
-  array.addParams(bp);
-  stmt.bindParameters(array);
-
-  stmt.executeAsync({
-    _errorObtained: false,
-    handleResult: function(aResultSet)
-    {
-      do_throw("Unexpected call to handleResult!");
-    },
-    handleError: function(aError)
-    {
-      print("Error code " + aError.result + " with message '" +
-            aError.message + "' returned.");
-      this._errorObtained = true;
-      do_check_eq(aError.result, Ci.mozIStorageError.MISMATCH);
-    },
-    handleCompletion: function(aReason)
-    {
-      print("handleCompletion(" + aReason +
-            ") for test_bind_bogus_type_by_name");
-      do_check_eq(Ci.mozIStorageStatementCallback.REASON_ERROR, aReason);
-      do_check_true(this._errorObtained);
-
-      // Run the next test.
-      run_next_test();
-    }
-  });
-  stmt.finalize();
-}
-
-function test_bind_params_already_locked()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-  bp.bindByName("int", INTEGER);
-  array.addParams(bp);
-
-  // We should get an error after we call addParams and try to bind again.
-  let exceptionCaught = false;
-  try {
-    bp.bindByName("int", INTEGER);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_bind_params_array_already_locked()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-
-  let array = stmt.newBindingParamsArray();
-  let bp1 = array.newBindingParams();
-  bp1.bindByName("int", INTEGER);
-  array.addParams(bp1);
-  let bp2 = array.newBindingParams();
-  stmt.bindParameters(array);
-  bp2.bindByName("int", INTEGER);
-
-  // We should get an error after we have bound the array to the statement.
-  let exceptionCaught = false;
-  try {
-    array.addParams(bp2);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_no_binding_params_from_locked_array()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-
-  let array = stmt.newBindingParamsArray();
-  let bp = array.newBindingParams();
-  bp.bindByName("int", INTEGER);
-  array.addParams(bp);
-  stmt.bindParameters(array);
-
-  // We should not be able to get a new BindingParams object after we have bound
-  // to the statement.
-  let exceptionCaught = false;
-  try {
-    bp = array.newBindingParams();
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_not_right_owning_array()
-{
-  let stmt = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-
-  let array1 = stmt.newBindingParamsArray();
-  let array2 = stmt.newBindingParamsArray();
-  let bp = array1.newBindingParams();
-  bp.bindByName("int", INTEGER);
-
-  // We should not be able to add bp to array2 since it was created from array1.
-  let exceptionCaught = false;
-  try {
-    array2.addParams(bp);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Run the next test.
-  run_next_test();
-}
-
-function test_not_right_owning_statement()
-{
-  let stmt1 = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-  let stmt2 = getOpenedDatabase().createStatement(
-    "INSERT INTO test (id) " +
-    "VALUES (:int)"
-  );
-
-  let array1 = stmt1.newBindingParamsArray();
-  let array2 = stmt2.newBindingParamsArray();
-  let bp = array1.newBindingParams();
-  bp.bindByName("int", INTEGER);
-  array1.addParams(bp);
-
-  // We should not be able to bind array1 since it was created from stmt1.
-  let exceptionCaught = false;
-  try {
-    stmt2.bindParameters(array1);
-    do_throw("we should have an exception!");
-  }
-  catch(e) {
-    do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
-    exceptionCaught = true;
-  }
-  do_check_true(exceptionCaught);
-
-  // Run the next test.
-  run_next_test();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// Test Runner
-
-var tests =
-[
-  test_create_table,
-  test_add_data,
-  test_get_data,
-  test_tuple_out_of_bounds,
-  test_no_listener_works_on_success,
-  test_no_listener_works_on_results,
-  test_no_listener_works_on_error,
-  test_partial_listener_works,
-  test_immediate_cancellation,
-  test_double_cancellation,
-  test_double_execute,
-  test_finalized_statement_does_not_crash,
-  test_bind_multiple_rows_by_index,
-  test_bind_multiple_rows_by_name,
-  test_bind_out_of_bounds,
-  test_bind_no_such_name,
-  test_bind_bogus_type_by_index,
-  test_bind_bogus_type_by_name,
-  test_bind_params_already_locked,
-  test_bind_params_array_already_locked,
-  test_no_binding_params_from_locked_array,
-  test_not_right_owning_array,
-  test_not_right_owning_statement,
-];
-let index = 0;
-
-function run_next_test()
-{
-  if (index < tests.length) {
-    do_test_pending();
-    print("Running the next test: " + tests[index].name);
-    tests[index++]();
-  }
-
-  do_test_finished();
-}
-
-function run_test()
-{
-  cleanup();
-
-  do_test_pending();
-  run_next_test();
-}
new file mode 100644
--- /dev/null
+++ b/storage/test/unit/test_storage_statement_executeAsync.js
@@ -0,0 +1,521 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Storage Test Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file tests the functionality of mozIStorageStatement::executeAsync
+
+const INTEGER = 1;
+const TEXT = "this is test text";
+const REAL = 3.23;
+const BLOB = [1, 2];
+
+function test_create_table()
+{
+  dump("test_create_table()\n");
+
+  // Ensure our table doesn't exists
+  do_check_false(getOpenedDatabase().tableExists("test"));
+
+  var stmt = getOpenedDatabase().createStatement(
+    "CREATE TABLE test (" +
+      "id INTEGER PRIMARY KEY, " +
+      "string TEXT, " +
+      "number REAL, " +
+      "nuller NULL, " +
+      "blober BLOB" +
+    ")"
+  );
+
+  do_test_pending();
+  stmt.executeAsync({
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_throw("unexpected results obtained!");
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
+
+      // Check that the table has been created
+      do_check_true(getOpenedDatabase().tableExists("test"));
+
+      // Verify that it's created correctly (this will throw if it wasn't)
+      var stmt = getOpenedDatabase().createStatement(
+        "SELECT id, string, number, nuller, blober FROM test"
+      );
+      stmt.finalize();
+
+      // Now we run the rest of the tests
+      for (var i = 0; i < tests.length; i++)
+        tests[i]();
+
+      do_test_finished();
+    }
+  });
+  stmt.finalize();
+}
+
+function test_add_data()
+{
+  dump("test_add_data()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "INSERT INTO test (id, string, number, nuller, blober) VALUES (?, ?, ?, ?, ?)"
+  );
+  stmt.bindInt32Parameter(0, INTEGER);
+  stmt.bindStringParameter(1, TEXT);
+  stmt.bindDoubleParameter(2, REAL);
+  stmt.bindNullParameter(3);
+  stmt.bindBlobParameter(4, BLOB, BLOB.length);
+
+  do_test_pending();
+  stmt.executeAsync({
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_throw("unexpected results obtained!");
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
+
+      // Check that the result is in the table
+      var stmt = getOpenedDatabase().createStatement(
+        "SELECT string, number, nuller, blober FROM test WHERE id = ?"
+      );
+      stmt.bindInt32Parameter(0, INTEGER);
+      try {
+        do_check_true(stmt.executeStep());
+        do_check_eq(TEXT, stmt.getString(0));
+        do_check_eq(REAL, stmt.getDouble(1));
+        do_check_true(stmt.getIsNull(2));
+        var count = { value: 0 };
+        var blob = { value: null };
+        stmt.getBlob(3, count, blob);
+        do_check_eq(BLOB.length, count.value);
+        for (var i = 0; i < BLOB.length; i++)
+          do_check_eq(BLOB[i], blob.value[i]);
+      }
+      finally {
+        stmt.reset();
+        stmt.finalize();
+      }
+
+      do_test_finished();
+    }
+  });
+  stmt.finalize();
+}
+
+function test_get_data()
+{
+  dump("test_get_data()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "SELECT string, number, nuller, blober, id FROM test WHERE id = ?"
+  );
+  stmt.bindInt32Parameter(0, 1);
+
+  do_test_pending();
+  stmt.executeAsync({
+    resultObtained: false,
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_check_false(this.resultObtained);
+      this.resultObtained = true;
+
+      // Check that we have a result
+      var tuple = aResultSet.getNextRow();
+      do_check_neq(null, tuple);
+
+      // Check that it's what we expect
+      do_check_eq(tuple.getResultByName("string"), tuple.getResultByIndex(0));
+      do_check_eq(TEXT, tuple.getResultByName("string"));
+      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_TEXT,
+                  tuple.getTypeOfIndex(0));
+
+      do_check_eq(tuple.getResultByName("number"), tuple.getResultByIndex(1));
+      do_check_eq(REAL, tuple.getResultByName("number"));
+      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT,
+                  tuple.getTypeOfIndex(1));
+
+      do_check_eq(tuple.getResultByName("nuller"), tuple.getResultByIndex(2));
+      do_check_eq(null, tuple.getResultByName("nuller"));
+      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_NULL,
+                  tuple.getTypeOfIndex(2));
+
+      var blobByName = tuple.getResultByName("blober");
+      do_check_eq(BLOB.length, blobByName.length);
+      var blobByIndex = tuple.getResultByIndex(3);
+      do_check_eq(BLOB.length, blobByIndex.length);
+      for (var i = 0; i < BLOB.length; i++) {
+        do_check_eq(BLOB[i], blobByName[i]);
+        do_check_eq(BLOB[i], blobByIndex[i]);
+      }
+      var count = { value: 0 };
+      var blob = { value: null };
+      tuple.getBlob(3, count, blob);
+      do_check_eq(BLOB.length, count.value);
+      for (var i = 0; i < BLOB.length; i++)
+        do_check_eq(BLOB[i], blob.value[i]);
+      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_BLOB,
+                  tuple.getTypeOfIndex(3));
+
+      do_check_eq(tuple.getResultByName("id"), tuple.getResultByIndex(4));
+      do_check_eq(INTEGER, tuple.getResultByName("id"));
+      do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER,
+                  tuple.getTypeOfIndex(4));
+
+      // check that we have no more results
+      tuple = aResultSet.getNextRow();
+      do_check_eq(null, tuple);
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
+      do_check_true(this.resultObtained);
+      do_test_finished();
+    }
+  });
+  stmt.finalize();
+}
+
+function test_tuple_out_of_bounds()
+{
+  dump("test_tuple_out_of_bounds()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "SELECT string FROM test"
+  );
+
+  do_test_pending();
+  stmt.executeAsync({
+    resultObtained: false,
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_check_false(this.resultObtained);
+      this.resultObtained = true;
+
+      // Check that we have a result
+      var tuple = aResultSet.getNextRow();
+      do_check_neq(null, tuple);
+
+      // Check all out of bounds - should throw
+      var methods = [
+        "getTypeOfIndex",
+        "getInt32",
+        "getInt64",
+        "getDouble",
+        "getUTF8String",
+        "getString",
+        "getIsNull",
+      ];
+      for (var i in methods) {
+        try {
+          tuple[methods[i]](tuple.numEntries);
+          do_throw("did not throw :(");
+        }
+        catch (e) {
+          do_check_eq(Cr.NS_ERROR_ILLEGAL_VALUE, e.result);
+        }
+      }
+
+      // getBlob requires more args...
+      try {
+        var blob = { value: null };
+        var size = { value: 0 };
+        tuple.getBlob(tuple.numEntries, blob, size);
+        do_throw("did not throw :(");
+      }
+      catch (e) {
+        do_check_eq(Cr.NS_ERROR_ILLEGAL_VALUE, e.result);
+      }
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
+      do_check_true(this.resultObtained);
+      do_test_finished();
+    }
+  });
+  stmt.finalize();
+}
+
+function test_no_listener_works_on_success()
+{
+  dump("test_no_listener_works_on_success()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "DELETE FROM test WHERE id = ?"
+  );
+  stmt.bindInt32Parameter(0, 0);
+  stmt.executeAsync();
+  stmt.finalize();
+}
+
+function test_no_listener_works_on_results()
+{
+  dump("test_no_listener_works_on_results()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "SELECT ?"
+  );
+  stmt.bindInt32Parameter(0, 1);
+  stmt.executeAsync();
+  stmt.finalize();
+}
+
+function test_no_listener_works_on_error()
+{
+  return;
+  dump("test_no_listener_works_on_error()\n");
+
+  // commit without a transaction will trigger an error
+  var stmt = getOpenedDatabase().createStatement(
+    "COMMIT"
+  );
+  stmt.executeAsync();
+  stmt.finalize();
+}
+
+function test_partial_listener_works()
+{
+  dump("test_partial_listener_works()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "DELETE FROM test WHERE id = ?"
+  );
+  stmt.bindInt32Parameter(0, 0);
+  stmt.executeAsync({
+    handleResult: function(aResultSet)
+    {
+    }
+  });
+  stmt.executeAsync({
+    handleError: function(aError)
+    {
+    }
+  });
+  stmt.executeAsync({
+    handleCompletion: function(aReason)
+    {
+    }
+  });
+  stmt.finalize();
+}
+
+function test_immediate_cancellation()
+{
+  dump("test_immediate_cancelation()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "DELETE FROM test WHERE id = ?"
+  );
+  stmt.bindInt32Parameter(0, 0);
+  let reason = Ci.mozIStorageStatementCallback.REASON_CANCELED;
+  var pendingStatement = stmt.executeAsync({
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_throw("unexpected result!");
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(reason, aReason);
+      do_test_finished();
+    }
+  });
+  do_test_pending();
+
+  // Cancel immediately
+  if (!pendingStatement.cancel()) {
+    // It is possible that we finished before we canceled
+    reason = Ci.mozIStorageStatementCallback.REASON_FINISHED;
+  }
+
+  stmt.finalize();
+}
+
+function test_double_cancellation()
+{
+  dump("test_double_cancelation()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "DELETE FROM test WHERE id = ?"
+  );
+  stmt.bindInt32Parameter(0, 0);
+  let reason = Ci.mozIStorageStatementCallback.REASON_CANCELED;
+  var pendingStatement = stmt.executeAsync({
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+      do_throw("unexpected result!");
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(reason, aReason);
+      do_test_finished();
+    }
+  });
+  do_test_pending();
+
+  // Cancel immediately
+  if (!pendingStatement.cancel()) {
+    // It is possible that we finished before we canceled
+    reason = Ci.mozIStorageStatementCallback.REASON_FINISHED;
+  }
+
+  // And cancel again - expect an exception
+  try {
+    pendingStatement.cancel();
+    do_throw("function call should have thrown!");
+  }
+  catch (e) {
+    do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
+  }
+
+  stmt.finalize();
+}
+
+function test_double_execute()
+{
+  dump("test_double_execute()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "SELECT * FROM test"
+  );
+
+  var listener = {
+    handleResult: function(aResultSet)
+    {
+      dump("handleResult("+aResultSet+");\n");
+    },
+    handleError: function(aError)
+    {
+      dump("handleError("+aError+");\n");
+      do_throw("unexpected error!");
+    },
+    handleCompletion: function(aReason)
+    {
+      dump("handleCompletion("+aReason+");\n");
+      do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
+      do_test_finished();
+    }
+  }
+  do_test_pending();
+  stmt.executeAsync(listener);
+  do_test_pending();
+  stmt.executeAsync(listener);
+  stmt.finalize();
+}
+
+function test_finalized_statement_does_not_crash()
+{
+  dump("test_finalized_statement_does_not_crash()\n");
+
+  var stmt = getOpenedDatabase().createStatement(
+    "SELECT * FROM TEST"
+  );
+  stmt.finalize();
+  // we are concerned about a crash here; an error is fine.
+  try {
+    stmt.executeAsync();
+  }
+  catch (ex) {}
+}
+
+var tests =
+[
+  test_add_data,
+  test_get_data,
+  test_tuple_out_of_bounds,
+  test_no_listener_works_on_success,
+  test_no_listener_works_on_results,
+  test_no_listener_works_on_error,
+  test_partial_listener_works,
+  test_immediate_cancellation,
+  test_double_cancellation,
+  test_double_execute,
+  test_finalized_statement_does_not_crash,
+];
+
+function run_test()
+{
+  cleanup();
+
+  // This test has to run first and run to completion.  When it is done, it will
+  // run the rest of the tests.
+  test_create_table();
+}