| 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..287510320bd5ef222b9ec4a46f7b1a12deea93de
|
| --- /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_t database_id,
|
| + int64_t object_store_id,
|
| + int64_t 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_t database_id,
|
| + int64_t object_store_id) const {
|
| + int64_t 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_t database_id,
|
| + int64_t object_store_id,
|
| + int64_t 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_t database_id,
|
| + const IndexedDBObjectStoreMetadata& object_store,
|
| + const IndexedDBKey& primary_key, // makes a copy
|
| + bool key_was_generated,
|
| + const std::vector<int64_t>& 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_t, 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
|
|
|