OLD | NEW |
(Empty) | |
| 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/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 namespace content { |
| 17 |
| 18 IndexedDBObjectStoreImpl::IndexWriter::IndexWriter( |
| 19 const IndexedDBIndexMetadata& index_metadata) |
| 20 : index_metadata_(index_metadata) {} |
| 21 |
| 22 IndexedDBObjectStoreImpl::IndexWriter::IndexWriter( |
| 23 const IndexedDBIndexMetadata& index_metadata, |
| 24 const IndexedDBDatabase::IndexKeys& index_keys) |
| 25 : index_metadata_(index_metadata), index_keys_(index_keys) {} |
| 26 |
| 27 IndexedDBObjectStoreImpl::IndexWriter::~IndexWriter() {} |
| 28 |
| 29 bool IndexedDBObjectStoreImpl::IndexWriter::VerifyIndexKeys( |
| 30 IndexedDBBackingStore* backing_store, |
| 31 IndexedDBBackingStore::Transaction* transaction, |
| 32 int64 database_id, |
| 33 int64 object_store_id, |
| 34 int64 index_id, |
| 35 bool* can_add_keys, |
| 36 const IndexedDBKey& primary_key, |
| 37 string16* error_message) const { |
| 38 *can_add_keys = false; |
| 39 for (size_t i = 0; i < index_keys_.size(); ++i) { |
| 40 bool ok = AddingKeyAllowed(backing_store, |
| 41 transaction, |
| 42 database_id, |
| 43 object_store_id, |
| 44 index_id, |
| 45 (index_keys_)[i], |
| 46 primary_key, |
| 47 can_add_keys); |
| 48 if (!ok) |
| 49 return false; |
| 50 if (!*can_add_keys) { |
| 51 if (error_message) |
| 52 *error_message = ASCIIToUTF16("Unable to add key to index '") + |
| 53 index_metadata_.name + |
| 54 ASCIIToUTF16("': at least one key does not satisfy " |
| 55 "the uniqueness requirements."); |
| 56 return true; |
| 57 } |
| 58 } |
| 59 *can_add_keys = true; |
| 60 return true; |
| 61 } |
| 62 |
| 63 void IndexedDBObjectStoreImpl::IndexWriter::WriteIndexKeys( |
| 64 const IndexedDBBackingStore::RecordIdentifier& record_identifier, |
| 65 IndexedDBBackingStore* backing_store, |
| 66 IndexedDBBackingStore::Transaction* transaction, |
| 67 int64 database_id, |
| 68 int64 object_store_id) const { |
| 69 int64 index_id = index_metadata_.id; |
| 70 for (size_t i = 0; i < index_keys_.size(); ++i) { |
| 71 bool ok = backing_store->PutIndexDataForRecord(transaction, |
| 72 database_id, |
| 73 object_store_id, |
| 74 index_id, |
| 75 index_keys_[i], |
| 76 record_identifier); |
| 77 // This should have already been verified as a valid write during |
| 78 // verify_index_keys. |
| 79 DCHECK(ok); |
| 80 } |
| 81 } |
| 82 |
| 83 bool IndexedDBObjectStoreImpl::IndexWriter::AddingKeyAllowed( |
| 84 IndexedDBBackingStore* backing_store, |
| 85 IndexedDBBackingStore::Transaction* transaction, |
| 86 int64 database_id, |
| 87 int64 object_store_id, |
| 88 int64 index_id, |
| 89 const IndexedDBKey& index_key, |
| 90 const IndexedDBKey& primary_key, |
| 91 bool* allowed) const { |
| 92 *allowed = false; |
| 93 if (!index_metadata_.unique) { |
| 94 *allowed = true; |
| 95 return true; |
| 96 } |
| 97 |
| 98 scoped_ptr<IndexedDBKey> found_primary_key; |
| 99 bool found = false; |
| 100 bool ok = backing_store->KeyExistsInIndex(transaction, |
| 101 database_id, |
| 102 object_store_id, |
| 103 index_id, |
| 104 index_key, |
| 105 &found_primary_key, |
| 106 found); |
| 107 if (!ok) |
| 108 return false; |
| 109 if (!found || |
| 110 (primary_key.IsValid() && found_primary_key->IsEqual(primary_key))) |
| 111 *allowed = true; |
| 112 return true; |
| 113 } |
| 114 |
| 115 bool IndexedDBObjectStoreImpl::MakeIndexWriters( |
| 116 scoped_refptr<IndexedDBTransaction> transaction, |
| 117 IndexedDBBackingStore* backing_store, |
| 118 int64 database_id, |
| 119 const IndexedDBObjectStoreMetadata& object_store, |
| 120 const IndexedDBKey& primary_key, // makes a copy |
| 121 bool key_was_generated, |
| 122 const std::vector<int64>& index_ids, |
| 123 const std::vector<IndexedDBDatabase::IndexKeys>& index_keys, |
| 124 ScopedVector<IndexWriter>* index_writers, |
| 125 string16* error_message, |
| 126 bool* completed) { |
| 127 DCHECK_EQ(index_ids.size(), index_keys.size()); |
| 128 *completed = false; |
| 129 |
| 130 std::map<int64, IndexedDBDatabase::IndexKeys> index_key_map; |
| 131 for (size_t i = 0; i < index_ids.size(); ++i) |
| 132 index_key_map[index_ids[i]] = index_keys[i]; |
| 133 |
| 134 for (IndexedDBObjectStoreMetadata::IndexMap::const_iterator it = |
| 135 object_store.indexes.begin(); |
| 136 it != object_store.indexes.end(); |
| 137 ++it) { |
| 138 const IndexedDBIndexMetadata& index = it->second; |
| 139 |
| 140 IndexedDBDatabase::IndexKeys keys = index_key_map[it->first]; |
| 141 // If the object_store is using auto_increment, then any indexes with an |
| 142 // identical key_path need to also use the primary (generated) key as a key. |
| 143 if (key_was_generated && (index.key_path == object_store.key_path)) |
| 144 keys.push_back(primary_key); |
| 145 |
| 146 scoped_ptr<IndexWriter> index_writer(new IndexWriter(index, keys)); |
| 147 bool can_add_keys = false; |
| 148 bool backing_store_success = |
| 149 index_writer->VerifyIndexKeys(backing_store, |
| 150 transaction->BackingStoreTransaction(), |
| 151 database_id, |
| 152 object_store.id, |
| 153 index.id, |
| 154 &can_add_keys, |
| 155 primary_key, |
| 156 error_message); |
| 157 if (!backing_store_success) |
| 158 return false; |
| 159 if (!can_add_keys) |
| 160 return true; |
| 161 |
| 162 index_writers->push_back(index_writer.release()); |
| 163 } |
| 164 |
| 165 *completed = true; |
| 166 return true; |
| 167 } |
| 168 |
| 169 } // namespace content |
OLD | NEW |