Cache put statements to avoid the cost of recreating them all the time.
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Thu, 06 May 2010 10:59:31 -0700
changeset 43979 a016bd48d084243bca556a5461d6887d6fd451ad
parent 43978 9d2c12b84af139c87789e63a245430dcf2b69edd
child 43980 4fc61aed70cd948eb796ecde82c41092e107eee9
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone1.9.3a5pre
Cache put statements to avoid the cost of recreating them all the time.
dom/indexedDB/IDBDatabaseRequest.cpp
dom/indexedDB/IDBDatabaseRequest.h
dom/indexedDB/IDBObjectStoreRequest.cpp
--- a/dom/indexedDB/IDBDatabaseRequest.cpp
+++ b/dom/indexedDB/IDBDatabaseRequest.cpp
@@ -497,16 +497,66 @@ IDBDatabaseRequest::EnsureConnection()
     "PRAGMA foreign_keys = ON;"
   ));
 #endif
 
   connection.swap(mConnection);
   return NS_OK;
 }
 
+already_AddRefed<mozIStorageStatement>
+IDBDatabaseRequest::PutStatement(bool aOverwrite,
+                                 bool aAutoIncrement)
+{
+  NS_PRECONDITION(!NS_IsMainThread(), "Wrong thread!");
+  (void)EnsureConnection();
+
+  if (aOverwrite) {
+    if (aAutoIncrement) {
+      if (!mPutOverwriteAutoIncrementStmt) {
+        nsresult rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
+          "INSERT OR REPLACE INTO ai_object_data (object_store_id, id, data) "
+          "VALUES (:osid, :key_value, :data)"
+        ), getter_AddRefs(mPutOverwriteAutoIncrementStmt));
+        NS_ENSURE_SUCCESS(rv, nsnull);
+      }
+      return mPutOverwriteAutoIncrementStmt;
+    }
+
+    if (!mPutOverwriteStmt) {
+      nsresult rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
+        "INSERT OR REPLACE INTO object_data (object_store_id, key_value, data) "
+        "VALUES (:osid, :key_value, :data)"
+      ), getter_AddRefs(mPutOverwriteStmt));
+      NS_ENSURE_SUCCESS(rv, nsnull);
+    }
+    return mPutOverwriteStmt;
+  }
+
+  if (aAutoIncrement) {
+    if (!mPutAutoIncrementStmt) {
+      nsresult rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
+        "INSERT INTO ai_object_data (object_store_id, data) "
+        "VALUES (:osid, :data)"
+      ), getter_AddRefs(mPutAutoIncrementStmt));
+      NS_ENSURE_SUCCESS(rv, nsnull);
+    }
+    return mPutAutoIncrementStmt;
+  }
+
+  if (!mPutStmt) {
+    nsresult rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
+      "INSERT INTO object_data (object_store_id, key_value, data) "
+      "VALUES (:osid, :key_value, :data)"
+    ), getter_AddRefs(mPutStmt));
+    NS_ENSURE_SUCCESS(rv, nsnull);
+  }
+  return mPutStmt;
+}
+
 void
 IDBDatabaseRequest::FireCloseConnectionRunnable()
 {
   nsRefPtr<CloseConnectionRunnable> runnable =
     new CloseConnectionRunnable(mConnectionThread, mConnection);
   runnable->Dispatch();
 }
 
--- a/dom/indexedDB/IDBDatabaseRequest.h
+++ b/dom/indexedDB/IDBDatabaseRequest.h
@@ -72,16 +72,31 @@ public:
          PRBool aReadOnly);
 
   // Only meant to be called on mStorageThread!
   nsCOMPtr<mozIStorageConnection>& Connection();
 
   // Only meant to be called on mStorageThread!
   nsresult EnsureConnection();
 
+  /**
+   * Obtains a cached statement for the put operation on object stores.
+   *
+   * @pre Called from mStorageThread.
+   *
+   * @param aOverwrite
+   *        Indicating if the operation should overwrite an existing entry or
+   *        not.
+   * @param aAutoIncrement
+   *        Indicating if the operation should use our key generator or not.
+   * @returns a mozIStorageStatement to use for the put operation.
+   */
+  already_AddRefed<mozIStorageStatement> PutStatement(bool aOverwrite,
+                                                      bool aAutoIncrement);
+
   nsIThread* ConnectionThread() {
     return mConnectionThread;
   }
 
   void FireCloseConnectionRunnable();
 
   void OnObjectStoreCreated(const nsAString& aName);
   void OnIndexCreated(const nsAString& aName);
@@ -102,13 +117,17 @@ private:
   nsTArray<nsString> mIndexNames;
 
   nsCOMPtr<nsIIDBTransaction> mCurrentTransaction;
 
   nsRefPtr<LazyIdleThread> mConnectionThread;
 
   // Only touched on mStorageThread!
   nsCOMPtr<mozIStorageConnection> mConnection;
+  nsCOMPtr<mozIStorageStatement> mPutStmt;
+  nsCOMPtr<mozIStorageStatement> mPutAutoIncrementStmt;
+  nsCOMPtr<mozIStorageStatement> mPutOverwriteStmt;
+  nsCOMPtr<mozIStorageStatement> mPutOverwriteAutoIncrementStmt;
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_idbdatabaserequest_h__
--- a/dom/indexedDB/IDBObjectStoreRequest.cpp
+++ b/dom/indexedDB/IDBObjectStoreRequest.cpp
@@ -421,33 +421,20 @@ PutHelper::DoDatabaseWork()
   nsresult rv = mDatabase->EnsureConnection();
   NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseError::UNKNOWN_ERR);
 
   nsCOMPtr<mozIStorageConnection> connection = mDatabase->Connection();
 
   // Rollback on any errors.
   mozStorageTransaction transaction(connection, PR_FALSE);
 
-  // TODO handle overwrite = true (use OR REPLACE?)
-
-  // XXX pull statement creation into mDatabase or something for efficiency.
-  nsCOMPtr<mozIStorageStatement> stmt;
-  if (mAutoIncrement) {
-    rv = connection->CreateStatement(NS_LITERAL_CSTRING(
-      "INSERT INTO ai_object_data (object_store_id, data)"
-      "VALUES (:osid, :data)"
-    ), getter_AddRefs(stmt));
-  }
-  else {
-    rv = connection->CreateStatement(NS_LITERAL_CSTRING(
-      "INSERT INTO object_data (object_store_id, key_value, data)"
-      "VALUES (:osid, :key_value, :data)"
-    ), getter_AddRefs(stmt));
-    NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseError::UNKNOWN_ERR);
-
+  nsCOMPtr<mozIStorageStatement> stmt =
+    mDatabase->PutStatement(!mNoOverwrite, mAutoIncrement);
+  NS_ENSURE_TRUE(stmt, nsIIDBDatabaseError::UNKNOWN_ERR);
+  if (!mAutoIncrement || mAutoIncrement && !mNoOverwrite) {
     NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
 
     if (mKeyString.IsVoid()) {
       rv = stmt->BindInt64ByName(keyValue, mKeyInt);
     }
     else {
       rv = stmt->BindStringByName(keyValue, mKeyString);
     }