Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_index_writer.cc
blob0f5a25419ab7ed8686fbff9b289e9b9d97553871
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/indexed_db/indexed_db_index_writer.h"
7 #include "base/logging.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "content/browser/indexed_db/indexed_db_backing_store.h"
10 #include "content/browser/indexed_db/indexed_db_tracing.h"
11 #include "content/browser/indexed_db/indexed_db_transaction.h"
12 #include "content/common/indexed_db/indexed_db_key.h"
13 #include "content/common/indexed_db/indexed_db_key_path.h"
14 #include "content/common/indexed_db/indexed_db_key_range.h"
16 using base::ASCIIToUTF16;
18 namespace content {
20 IndexWriter::IndexWriter(
21 const IndexedDBIndexMetadata& index_metadata)
22 : index_metadata_(index_metadata) {}
24 IndexWriter::IndexWriter(
25 const IndexedDBIndexMetadata& index_metadata,
26 const IndexedDBDatabase::IndexKeys& index_keys)
27 : index_metadata_(index_metadata), index_keys_(index_keys) {}
29 IndexWriter::~IndexWriter() {}
31 bool IndexWriter::VerifyIndexKeys(
32 IndexedDBBackingStore* backing_store,
33 IndexedDBBackingStore::Transaction* transaction,
34 int64 database_id,
35 int64 object_store_id,
36 int64 index_id,
37 bool* can_add_keys,
38 const IndexedDBKey& primary_key,
39 base::string16* error_message) const {
40 *can_add_keys = false;
41 DCHECK_EQ(index_id, index_keys_.first);
42 for (size_t i = 0; i < index_keys_.second.size(); ++i) {
43 bool ok = AddingKeyAllowed(backing_store,
44 transaction,
45 database_id,
46 object_store_id,
47 index_id,
48 (index_keys_.second)[i],
49 primary_key,
50 can_add_keys);
51 if (!ok)
52 return false;
53 if (!*can_add_keys) {
54 if (error_message) {
55 *error_message = ASCIIToUTF16("Unable to add key to index '") +
56 index_metadata_.name +
57 ASCIIToUTF16("': at least one key does not satisfy "
58 "the uniqueness requirements.");
60 return true;
63 *can_add_keys = true;
64 return true;
67 void IndexWriter::WriteIndexKeys(
68 const IndexedDBBackingStore::RecordIdentifier& record_identifier,
69 IndexedDBBackingStore* backing_store,
70 IndexedDBBackingStore::Transaction* transaction,
71 int64 database_id,
72 int64 object_store_id) const {
73 int64 index_id = index_metadata_.id;
74 DCHECK_EQ(index_id, index_keys_.first);
75 for (size_t i = 0; i < index_keys_.second.size(); ++i) {
76 leveldb::Status s =
77 backing_store->PutIndexDataForRecord(transaction,
78 database_id,
79 object_store_id,
80 index_id,
81 index_keys_.second[i],
82 record_identifier);
83 // This should have already been verified as a valid write during
84 // verify_index_keys.
85 DCHECK(s.ok());
89 bool IndexWriter::AddingKeyAllowed(
90 IndexedDBBackingStore* backing_store,
91 IndexedDBBackingStore::Transaction* transaction,
92 int64 database_id,
93 int64 object_store_id,
94 int64 index_id,
95 const IndexedDBKey& index_key,
96 const IndexedDBKey& primary_key,
97 bool* allowed) const {
98 *allowed = false;
99 if (!index_metadata_.unique) {
100 *allowed = true;
101 return true;
104 scoped_ptr<IndexedDBKey> found_primary_key;
105 bool found = false;
106 leveldb::Status s = backing_store->KeyExistsInIndex(transaction,
107 database_id,
108 object_store_id,
109 index_id,
110 index_key,
111 &found_primary_key,
112 &found);
113 if (!s.ok())
114 return false;
115 if (!found ||
116 (primary_key.IsValid() && found_primary_key->Equals(primary_key)))
117 *allowed = true;
118 return true;
121 bool MakeIndexWriters(
122 IndexedDBTransaction* transaction,
123 IndexedDBBackingStore* backing_store,
124 int64 database_id,
125 const IndexedDBObjectStoreMetadata& object_store,
126 const IndexedDBKey& primary_key, // makes a copy
127 bool key_was_generated,
128 const std::vector<IndexedDBDatabase::IndexKeys>& index_keys,
129 ScopedVector<IndexWriter>* index_writers,
130 base::string16* error_message,
131 bool* completed) {
132 *completed = false;
134 for (std::vector<IndexedDBDatabase::IndexKeys>::const_iterator it =
135 index_keys.begin();
136 it != index_keys.end();
137 ++it) {
138 IndexedDBObjectStoreMetadata::IndexMap::const_iterator found =
139 object_store.indexes.find(it->first);
140 if (found == object_store.indexes.end())
141 continue;
142 const IndexedDBIndexMetadata& index = found->second;
143 IndexedDBDatabase::IndexKeys keys = *it;
145 // If the object_store is using auto_increment, then any indexes with an
146 // identical key_path need to also use the primary (generated) key as a key.
147 if (key_was_generated && (index.key_path == object_store.key_path))
148 keys.second.push_back(primary_key);
150 scoped_ptr<IndexWriter> index_writer(new IndexWriter(index, keys));
151 bool can_add_keys = false;
152 bool backing_store_success =
153 index_writer->VerifyIndexKeys(backing_store,
154 transaction->BackingStoreTransaction(),
155 database_id,
156 object_store.id,
157 index.id,
158 &can_add_keys,
159 primary_key,
160 error_message);
161 if (!backing_store_success)
162 return false;
163 if (!can_add_keys)
164 return true;
166 index_writers->push_back(index_writer.release());
169 *completed = true;
170 return true;
173 } // namespace content