Index: content/browser/indexed_db/indexed_db_index_writer.cc |
diff --git a/content/browser/indexed_db/indexed_db_index_writer.cc b/content/browser/indexed_db/indexed_db_index_writer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6104111ae3023e0c7d8e5fcfc5326fdc5cf40f62 |
--- /dev/null |
+++ b/content/browser/indexed_db/indexed_db_index_writer.cc |
@@ -0,0 +1,169 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/indexed_db/indexed_db_index_writer.h" |
+ |
+#include "base/logging.h" |
+#include "base/utf_string_conversions.h" |
+#include "content/browser/indexed_db/indexed_db_backing_store.h" |
+#include "content/browser/indexed_db/indexed_db_tracing.h" |
+#include "content/browser/indexed_db/indexed_db_transaction.h" |
+#include "content/common/indexed_db/indexed_db_key.h" |
+#include "content/common/indexed_db/indexed_db_key_path.h" |
+#include "content/common/indexed_db/indexed_db_key_range.h" |
+ |
+namespace content { |
+ |
+IndexedDBObjectStoreImpl::IndexWriter::IndexWriter( |
+ const IndexedDBIndexMetadata& index_metadata) |
+ : index_metadata_(index_metadata) {} |
+ |
+IndexedDBObjectStoreImpl::IndexWriter::IndexWriter( |
+ const IndexedDBIndexMetadata& index_metadata, |
+ const IndexedDBDatabase::IndexKeys& index_keys) |
+ : index_metadata_(index_metadata), index_keys_(index_keys) {} |
+ |
+IndexedDBObjectStoreImpl::IndexWriter::~IndexWriter() {} |
+ |
+bool IndexedDBObjectStoreImpl::IndexWriter::VerifyIndexKeys( |
+ IndexedDBBackingStore* backing_store, |
+ IndexedDBBackingStore::Transaction* transaction, |
+ int64 database_id, |
+ int64 object_store_id, |
+ int64 index_id, |
+ bool* can_add_keys, |
+ const IndexedDBKey& primary_key, |
+ string16* error_message) const { |
+ *can_add_keys = false; |
+ for (size_t i = 0; i < index_keys_.size(); ++i) { |
+ bool ok = AddingKeyAllowed(backing_store, |
+ transaction, |
+ database_id, |
+ object_store_id, |
+ index_id, |
+ (index_keys_)[i], |
+ primary_key, |
+ can_add_keys); |
+ if (!ok) |
+ return false; |
+ if (!*can_add_keys) { |
+ if (error_message) |
+ *error_message = ASCIIToUTF16("Unable to add key to index '") + |
+ index_metadata_.name + |
+ ASCIIToUTF16("': at least one key does not satisfy " |
+ "the uniqueness requirements."); |
+ return true; |
+ } |
+ } |
+ *can_add_keys = true; |
+ return true; |
+} |
+ |
+void IndexedDBObjectStoreImpl::IndexWriter::WriteIndexKeys( |
+ const IndexedDBBackingStore::RecordIdentifier& record_identifier, |
+ IndexedDBBackingStore* backing_store, |
+ IndexedDBBackingStore::Transaction* transaction, |
+ int64 database_id, |
+ int64 object_store_id) const { |
+ int64 index_id = index_metadata_.id; |
+ for (size_t i = 0; i < index_keys_.size(); ++i) { |
+ bool ok = backing_store->PutIndexDataForRecord(transaction, |
+ database_id, |
+ object_store_id, |
+ index_id, |
+ index_keys_[i], |
+ record_identifier); |
+ // This should have already been verified as a valid write during |
+ // verify_index_keys. |
+ DCHECK(ok); |
+ } |
+} |
+ |
+bool IndexedDBObjectStoreImpl::IndexWriter::AddingKeyAllowed( |
+ IndexedDBBackingStore* backing_store, |
+ IndexedDBBackingStore::Transaction* transaction, |
+ int64 database_id, |
+ int64 object_store_id, |
+ int64 index_id, |
+ const IndexedDBKey& index_key, |
+ const IndexedDBKey& primary_key, |
+ bool* allowed) const { |
+ *allowed = false; |
+ if (!index_metadata_.unique) { |
+ *allowed = true; |
+ return true; |
+ } |
+ |
+ scoped_ptr<IndexedDBKey> found_primary_key; |
+ bool found = false; |
+ bool ok = backing_store->KeyExistsInIndex(transaction, |
+ database_id, |
+ object_store_id, |
+ index_id, |
+ index_key, |
+ &found_primary_key, |
+ found); |
+ if (!ok) |
+ return false; |
+ if (!found || |
+ (primary_key.IsValid() && found_primary_key->IsEqual(primary_key))) |
+ *allowed = true; |
+ return true; |
+} |
+ |
+bool IndexedDBObjectStoreImpl::MakeIndexWriters( |
+ scoped_refptr<IndexedDBTransaction> transaction, |
+ IndexedDBBackingStore* backing_store, |
+ int64 database_id, |
+ const IndexedDBObjectStoreMetadata& object_store, |
+ const IndexedDBKey& primary_key, // makes a copy |
+ bool key_was_generated, |
+ const std::vector<int64>& index_ids, |
+ const std::vector<IndexedDBDatabase::IndexKeys>& index_keys, |
+ ScopedVector<IndexWriter>* index_writers, |
+ string16* error_message, |
+ bool* completed) { |
+ DCHECK_EQ(index_ids.size(), index_keys.size()); |
+ *completed = false; |
+ |
+ std::map<int64, IndexedDBDatabase::IndexKeys> index_key_map; |
+ for (size_t i = 0; i < index_ids.size(); ++i) |
+ index_key_map[index_ids[i]] = index_keys[i]; |
+ |
+ for (IndexedDBObjectStoreMetadata::IndexMap::const_iterator it = |
+ object_store.indexes.begin(); |
+ it != object_store.indexes.end(); |
+ ++it) { |
+ const IndexedDBIndexMetadata& index = it->second; |
+ |
+ IndexedDBDatabase::IndexKeys keys = index_key_map[it->first]; |
+ // If the object_store is using auto_increment, then any indexes with an |
+ // identical key_path need to also use the primary (generated) key as a key. |
+ if (key_was_generated && (index.key_path == object_store.key_path)) |
+ keys.push_back(primary_key); |
+ |
+ scoped_ptr<IndexWriter> index_writer(new IndexWriter(index, keys)); |
+ bool can_add_keys = false; |
+ bool backing_store_success = |
+ index_writer->VerifyIndexKeys(backing_store, |
+ transaction->BackingStoreTransaction(), |
+ database_id, |
+ object_store.id, |
+ index.id, |
+ &can_add_keys, |
+ primary_key, |
+ error_message); |
+ if (!backing_store_success) |
+ return false; |
+ if (!can_add_keys) |
+ return true; |
+ |
+ index_writers->push_back(index_writer.release()); |
+ } |
+ |
+ *completed = true; |
+ return true; |
+} |
+ |
+} // namespace content |