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
;
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
,
35 int64 object_store_id
,
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
,
48 (index_keys_
.second
)[i
],
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.");
67 void IndexWriter::WriteIndexKeys(
68 const IndexedDBBackingStore::RecordIdentifier
& record_identifier
,
69 IndexedDBBackingStore
* backing_store
,
70 IndexedDBBackingStore::Transaction
* transaction
,
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
) {
77 backing_store
->PutIndexDataForRecord(transaction
,
81 index_keys_
.second
[i
],
83 // This should have already been verified as a valid write during
89 bool IndexWriter::AddingKeyAllowed(
90 IndexedDBBackingStore
* backing_store
,
91 IndexedDBBackingStore::Transaction
* transaction
,
93 int64 object_store_id
,
95 const IndexedDBKey
& index_key
,
96 const IndexedDBKey
& primary_key
,
97 bool* allowed
) const {
99 if (!index_metadata_
.unique
) {
104 scoped_ptr
<IndexedDBKey
> found_primary_key
;
106 leveldb::Status s
= backing_store
->KeyExistsInIndex(transaction
,
116 (primary_key
.IsValid() && found_primary_key
->Equals(primary_key
)))
121 bool MakeIndexWriters(
122 IndexedDBTransaction
* transaction
,
123 IndexedDBBackingStore
* backing_store
,
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
,
134 for (const auto& it
: index_keys
) {
135 IndexedDBObjectStoreMetadata::IndexMap::const_iterator found
=
136 object_store
.indexes
.find(it
.first
);
137 if (found
== object_store
.indexes
.end())
139 const IndexedDBIndexMetadata
& index
= found
->second
;
140 IndexedDBDatabase::IndexKeys keys
= it
;
142 // If the object_store is using auto_increment, then any indexes with an
143 // identical key_path need to also use the primary (generated) key as a key.
144 if (key_was_generated
&& (index
.key_path
== object_store
.key_path
))
145 keys
.second
.push_back(primary_key
);
147 scoped_ptr
<IndexWriter
> index_writer(new IndexWriter(index
, keys
));
148 bool can_add_keys
= false;
149 bool backing_store_success
=
150 index_writer
->VerifyIndexKeys(backing_store
,
151 transaction
->BackingStoreTransaction(),
158 if (!backing_store_success
)
163 index_writers
->push_back(index_writer
.release());
170 } // namespace content