Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_index_writer.cc
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.
4
5 #include "content/browser/indexed_db/indexed_db_index_writer.h"
6
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"
15
16 using base::ASCIIToUTF16;
17
18 namespace content {
19
20 IndexWriter::IndexWriter(
21     const IndexedDBIndexMetadata& index_metadata)
22     : index_metadata_(index_metadata) {}
23
24 IndexWriter::IndexWriter(
25     const IndexedDBIndexMetadata& index_metadata,
26     const IndexedDBDatabase::IndexKeys& index_keys)
27     : index_metadata_(index_metadata), index_keys_(index_keys) {}
28
29 IndexWriter::~IndexWriter() {}
30
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.");
59       }
60       return true;
61     }
62   }
63   *can_add_keys = true;
64   return true;
65 }
66
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());
86   }
87 }
88
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;
102   }
103
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;
119 }
120
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;
133
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())
138       continue;
139     const IndexedDBIndexMetadata& index = found->second;
140     IndexedDBDatabase::IndexKeys keys = it;
141
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);
146
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(),
152                                       database_id,
153                                       object_store.id,
154                                       index.id,
155                                       &can_add_keys,
156                                       primary_key,
157                                       error_message);
158     if (!backing_store_success)
159       return false;
160     if (!can_add_keys)
161       return true;
162
163     index_writers->push_back(index_writer.release());
164   }
165
166   *completed = true;
167   return true;
168 }
169
170 }  // namespace content