diff options
Diffstat (limited to 'content/browser/indexed_db/indexed_db_index_writer.cc')
-rw-r--r-- | content/browser/indexed_db/indexed_db_index_writer.cc | 169 |
1 files changed, 169 insertions, 0 deletions
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 0000000..6104111 --- /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 |