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_leveldb_coding.h"
10 #include "base/logging.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/sys_byteorder.h"
14 #include "content/common/indexed_db/indexed_db_key.h"
15 #include "content/common/indexed_db/indexed_db_key_path.h"
17 // LevelDB Coding Scheme
18 // =====================
20 // LevelDB stores key/value pairs. Keys and values are strings of bytes,
21 // normally of type std::string.
23 // The keys in the backing store are variable-length tuples with different
24 // types of fields. Each key in the backing store starts with a ternary
25 // prefix: (database id, object store id, index id). For each, 0 is reserved
26 // for metadata. See KeyPrefix::Decode() for details of the prefix coding.
28 // The prefix makes sure that data for a specific database, object store, and
29 // index are grouped together. The locality is important for performance:
30 // common operations should only need a minimal number of seek operations. For
31 // example, all the metadata for a database is grouped together so that
32 // reading that metadata only requires one seek.
34 // Each key type has a class (in square brackets below) which knows how to
35 // encode, decode, and compare that key type.
37 // Strings (origins, names, etc) are encoded as UTF-16BE.
42 // The prefix is <0, 0, 0>, followed by a metadata type byte:
44 // <0, 0, 0, 0> => backing store schema version [SchemaVersionKey]
45 // <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey]
46 // <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey]
49 // The format of the journal is: {database_id, blobKey}*.
50 // If the blobKey is kAllBlobsKey, the whole database should be deleted.
52 // <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
53 // <0, 0, 0, 100, database id>
54 // => Existence implies the database id is in the free list
55 // [DatabaseFreeListKey]
56 // <0, 0, 0, 201, origin, database name> => Database id [DatabaseNameKey]
59 // Database metadata: [DatabaseMetaDataKey]
60 // ----------------------------------------
61 // The prefix is <database id, 0, 0> followed by a metadata type byte:
63 // <database id, 0, 0, 0> => origin name
64 // <database id, 0, 0, 1> => database name
65 // <database id, 0, 0, 2> => IDB string version data (obsolete)
66 // <database id, 0, 0, 3> => maximum allocated object store id
67 // <database id, 0, 0, 4> => IDB integer version (var int)
68 // <database id, 0, 0, 5> => blob key generator current number
71 // Object store metadata: [ObjectStoreMetaDataKey]
72 // -----------------------------------------------
73 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
74 // object store id (var int), then a metadata type byte.
76 // <database id, 0, 0, 50, object store id, 0> => object store name
77 // <database id, 0, 0, 50, object store id, 1> => key path
78 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
79 // <database id, 0, 0, 50, object store id, 3> => is evictable
80 // <database id, 0, 0, 50, object store id, 4> => last "version" number
81 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
82 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
83 // <database id, 0, 0, 50, object store id, 7> => key generator current number
85 // The key path was originally just a string (#1) or null (identified by flag,
86 // #6). To support null, string, or array the coding is now identified by the
87 // leading bytes in #1 - see EncodeIDBKeyPath.
89 // The "version" field is used to weed out stale index data. Whenever new
90 // object store data is inserted, it gets a new "version" number, and new
91 // index data is written with this number. When the index is used for
92 // look-ups, entries are validated against the "exists" entries, and records
93 // with old "version" numbers are deleted when they are encountered in
94 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
95 // IndexKeyCursorImpl::LoadCurrentRow.
98 // Index metadata: [IndexMetaDataKey]
99 // ----------------------------------
100 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
101 // object store id (var int), then the index id (var int), then a metadata
104 // <database id, 0, 0, 100, object store id, index id, 0> => index name
105 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
106 // <database id, 0, 0, 100, object store id, index id, 2> => key path
107 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
110 // Other object store and index metadata
111 // -------------------------------------
112 // The prefix is <database id, 0, 0> followed by a type byte. The object
113 // store and index id are variable length integers, the names are variable
116 // <database id, 0, 0, 150, object store id>
117 // => existence implies the object store id is in the free list
118 // [ObjectStoreFreeListKey]
119 // <database id, 0, 0, 151, object store id, index id>
120 // => existence implies the index id is in the free list [IndexFreeListKey]
121 // <database id, 0, 0, 200, object store name>
122 // => object store id [ObjectStoreNamesKey]
123 // <database id, 0, 0, 201, object store id, index name>
124 // => index id [IndexNamesKey]
127 // Object store data: [ObjectStoreDataKey]
128 // ---------------------------------------
129 // The prefix is followed by a type byte and the encoded IDB primary key. The
130 // data has a "version" prefix followed by the serialized script value.
132 // <database id, object store id, 1, user key>
133 // => "version", serialized script value
136 // "Exists" entry: [ExistsEntryKey]
137 // --------------------------------
138 // The prefix is followed by a type byte and the encoded IDB primary key.
140 // <database id, object store id, 2, user key> => "version"
143 // Blob entry table: [BlobEntryKey]
144 // --------------------------------
146 // The prefix is followed by a type byte and the encoded IDB primary key.
148 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
153 // The prefix is followed by a type byte, the encoded IDB index key, a
154 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
156 // <database id, object store id, index id, index key, sequence number,
157 // primary key> => "version", primary key [IndexDataKey]
159 // The sequence number is obsolete; it was used to allow two entries with the
160 // same user (index) key in non-unique indexes prior to the inclusion of the
161 // primary key in the data.
163 using base::StringPiece
;
164 using blink::WebIDBKeyType
;
165 using blink::WebIDBKeyTypeArray
;
166 using blink::WebIDBKeyTypeBinary
;
167 using blink::WebIDBKeyTypeDate
;
168 using blink::WebIDBKeyTypeInvalid
;
169 using blink::WebIDBKeyTypeMin
;
170 using blink::WebIDBKeyTypeNull
;
171 using blink::WebIDBKeyTypeNumber
;
172 using blink::WebIDBKeyTypeString
;
173 using blink::WebIDBKeyPathType
;
174 using blink::WebIDBKeyPathTypeArray
;
175 using blink::WebIDBKeyPathTypeNull
;
176 using blink::WebIDBKeyPathTypeString
;
180 // As most of the IndexedDBKeys and encoded values are short, we
181 // initialize some std::vectors with a default inline buffer size to reduce
182 // the memory re-allocations when the std::vectors are appended.
183 static const size_t kDefaultInlineBufferSize
= 32;
185 static const unsigned char kIndexedDBKeyNullTypeByte
= 0;
186 static const unsigned char kIndexedDBKeyStringTypeByte
= 1;
187 static const unsigned char kIndexedDBKeyDateTypeByte
= 2;
188 static const unsigned char kIndexedDBKeyNumberTypeByte
= 3;
189 static const unsigned char kIndexedDBKeyArrayTypeByte
= 4;
190 static const unsigned char kIndexedDBKeyMinKeyTypeByte
= 5;
191 static const unsigned char kIndexedDBKeyBinaryTypeByte
= 6;
193 static const unsigned char kIndexedDBKeyPathTypeCodedByte1
= 0;
194 static const unsigned char kIndexedDBKeyPathTypeCodedByte2
= 0;
196 static const unsigned char kObjectStoreDataIndexId
= 1;
197 static const unsigned char kExistsEntryIndexId
= 2;
198 static const unsigned char kBlobEntryIndexId
= 3;
200 static const unsigned char kSchemaVersionTypeByte
= 0;
201 static const unsigned char kMaxDatabaseIdTypeByte
= 1;
202 static const unsigned char kDataVersionTypeByte
= 2;
203 static const unsigned char kBlobJournalTypeByte
= 3;
204 static const unsigned char kLiveBlobJournalTypeByte
= 4;
205 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte
=
206 5; // Insert before this and increment.
207 static const unsigned char kDatabaseFreeListTypeByte
= 100;
208 static const unsigned char kDatabaseNameTypeByte
= 201;
210 static const unsigned char kObjectStoreMetaDataTypeByte
= 50;
211 static const unsigned char kIndexMetaDataTypeByte
= 100;
212 static const unsigned char kObjectStoreFreeListTypeByte
= 150;
213 static const unsigned char kIndexFreeListTypeByte
= 151;
214 static const unsigned char kObjectStoreNamesTypeByte
= 200;
215 static const unsigned char kIndexNamesKeyTypeByte
= 201;
217 static const unsigned char kObjectMetaDataTypeMaximum
= 255;
218 static const unsigned char kIndexMetaDataTypeMaximum
= 255;
220 const unsigned char kMinimumIndexId
= 30;
222 inline void EncodeIntSafely(int64 nParam
, int64 max
, std::string
* into
) {
223 DCHECK_LE(nParam
, max
);
224 return EncodeInt(nParam
, into
);
227 std::string
MaxIDBKey() {
229 EncodeByte(kIndexedDBKeyNullTypeByte
, &ret
);
233 std::string
MinIDBKey() {
235 EncodeByte(kIndexedDBKeyMinKeyTypeByte
, &ret
);
239 void EncodeByte(unsigned char value
, std::string
* into
) {
240 into
->push_back(value
);
243 void EncodeBool(bool value
, std::string
* into
) {
244 into
->push_back(value
? 1 : 0);
247 void EncodeInt(int64 value
, std::string
* into
) {
249 // Exercised by unit tests in debug only.
252 uint64 n
= static_cast<uint64
>(value
);
261 void EncodeVarInt(int64 value
, std::string
* into
) {
263 // Exercised by unit tests in debug only.
266 uint64 n
= static_cast<uint64
>(value
);
269 unsigned char c
= n
& 0x7f;
277 void EncodeString(const base::string16
& value
, std::string
* into
) {
280 // Backing store is UTF-16BE, convert from host endianness.
281 size_t length
= value
.length();
282 size_t current
= into
->size();
283 into
->resize(into
->size() + length
* sizeof(base::char16
));
285 const base::char16
* src
= value
.c_str();
287 reinterpret_cast<base::char16
*>(&*into
->begin() + current
);
288 for (unsigned i
= 0; i
< length
; ++i
)
289 *dst
++ = htons(*src
++);
292 void EncodeBinary(const std::string
& value
, std::string
* into
) {
293 EncodeVarInt(value
.length(), into
);
294 into
->append(value
.begin(), value
.end());
295 DCHECK(into
->size() >= value
.size());
298 void EncodeStringWithLength(const base::string16
& value
, std::string
* into
) {
299 EncodeVarInt(value
.length(), into
);
300 EncodeString(value
, into
);
303 void EncodeDouble(double value
, std::string
* into
) {
304 // This always has host endianness.
305 const char* p
= reinterpret_cast<char*>(&value
);
306 into
->insert(into
->end(), p
, p
+ sizeof(value
));
309 void EncodeIDBKey(const IndexedDBKey
& value
, std::string
* into
) {
310 size_t previous_size
= into
->size();
311 DCHECK(value
.IsValid());
312 switch (value
.type()) {
313 case WebIDBKeyTypeArray
: {
314 EncodeByte(kIndexedDBKeyArrayTypeByte
, into
);
315 size_t length
= value
.array().size();
316 EncodeVarInt(length
, into
);
317 for (size_t i
= 0; i
< length
; ++i
)
318 EncodeIDBKey(value
.array()[i
], into
);
319 DCHECK_GT(into
->size(), previous_size
);
322 case WebIDBKeyTypeBinary
:
323 EncodeByte(kIndexedDBKeyBinaryTypeByte
, into
);
324 EncodeBinary(value
.binary(), into
);
325 DCHECK_GT(into
->size(), previous_size
);
327 case WebIDBKeyTypeString
:
328 EncodeByte(kIndexedDBKeyStringTypeByte
, into
);
329 EncodeStringWithLength(value
.string(), into
);
330 DCHECK_GT(into
->size(), previous_size
);
332 case WebIDBKeyTypeDate
:
333 EncodeByte(kIndexedDBKeyDateTypeByte
, into
);
334 EncodeDouble(value
.date(), into
);
335 DCHECK_EQ(9u, static_cast<size_t>(into
->size() - previous_size
));
337 case WebIDBKeyTypeNumber
:
338 EncodeByte(kIndexedDBKeyNumberTypeByte
, into
);
339 EncodeDouble(value
.number(), into
);
340 DCHECK_EQ(9u, static_cast<size_t>(into
->size() - previous_size
));
342 case WebIDBKeyTypeNull
:
343 case WebIDBKeyTypeInvalid
:
344 case WebIDBKeyTypeMin
:
347 EncodeByte(kIndexedDBKeyNullTypeByte
, into
);
352 void EncodeIDBKeyPath(const IndexedDBKeyPath
& value
, std::string
* into
) {
353 // May be typed, or may be a raw string. An invalid leading
354 // byte is used to identify typed coding. New records are
355 // always written as typed.
356 EncodeByte(kIndexedDBKeyPathTypeCodedByte1
, into
);
357 EncodeByte(kIndexedDBKeyPathTypeCodedByte2
, into
);
358 EncodeByte(static_cast<char>(value
.type()), into
);
359 switch (value
.type()) {
360 case WebIDBKeyPathTypeNull
:
362 case WebIDBKeyPathTypeString
: {
363 EncodeStringWithLength(value
.string(), into
);
366 case WebIDBKeyPathTypeArray
: {
367 const std::vector
<base::string16
>& array
= value
.array();
368 size_t count
= array
.size();
369 EncodeVarInt(count
, into
);
370 for (size_t i
= 0; i
< count
; ++i
) {
371 EncodeStringWithLength(array
[i
], into
);
378 bool DecodeByte(StringPiece
* slice
, unsigned char* value
) {
382 *value
= (*slice
)[0];
383 slice
->remove_prefix(1);
387 bool DecodeBool(StringPiece
* slice
, bool* value
) {
391 *value
= !!(*slice
)[0];
392 slice
->remove_prefix(1);
396 bool DecodeInt(StringPiece
* slice
, int64
* value
) {
400 StringPiece::const_iterator it
= slice
->begin();
403 while (it
!= slice
->end()) {
404 unsigned char c
= *it
++;
405 ret
|= static_cast<int64
>(c
) << shift
;
409 slice
->remove_prefix(it
- slice
->begin());
413 bool DecodeVarInt(StringPiece
* slice
, int64
* value
) {
417 StringPiece::const_iterator it
= slice
->begin();
421 if (it
== slice
->end())
424 unsigned char c
= *it
;
425 ret
|= static_cast<int64
>(c
& 0x7f) << shift
;
427 } while (*it
++ & 0x80);
429 slice
->remove_prefix(it
- slice
->begin());
433 bool DecodeString(StringPiece
* slice
, base::string16
* value
) {
434 if (slice
->empty()) {
439 // Backing store is UTF-16BE, convert to host endianness.
440 DCHECK(!(slice
->size() % sizeof(base::char16
)));
441 size_t length
= slice
->size() / sizeof(base::char16
);
442 base::string16 decoded
;
443 decoded
.reserve(length
);
444 const base::char16
* encoded
=
445 reinterpret_cast<const base::char16
*>(slice
->begin());
446 for (unsigned i
= 0; i
< length
; ++i
)
447 decoded
.push_back(ntohs(*encoded
++));
450 slice
->remove_prefix(length
* sizeof(base::char16
));
454 bool DecodeStringWithLength(StringPiece
* slice
, base::string16
* value
) {
459 if (!DecodeVarInt(slice
, &length
) || length
< 0)
461 size_t bytes
= length
* sizeof(base::char16
);
462 if (slice
->size() < bytes
)
465 StringPiece
subpiece(slice
->begin(), bytes
);
466 slice
->remove_prefix(bytes
);
467 if (!DecodeString(&subpiece
, value
))
473 bool DecodeBinary(StringPiece
* slice
, std::string
* value
) {
478 if (!DecodeVarInt(slice
, &length
) || length
< 0)
480 size_t size
= length
;
481 if (slice
->size() < size
)
484 value
->assign(slice
->begin(), size
);
485 slice
->remove_prefix(size
);
489 bool DecodeIDBKey(StringPiece
* slice
, scoped_ptr
<IndexedDBKey
>* value
) {
493 unsigned char type
= (*slice
)[0];
494 slice
->remove_prefix(1);
497 case kIndexedDBKeyNullTypeByte
:
498 *value
= make_scoped_ptr(new IndexedDBKey());
501 case kIndexedDBKeyArrayTypeByte
: {
503 if (!DecodeVarInt(slice
, &length
) || length
< 0)
505 IndexedDBKey::KeyArray array
;
507 scoped_ptr
<IndexedDBKey
> key
;
508 if (!DecodeIDBKey(slice
, &key
))
510 array
.push_back(*key
);
512 *value
= make_scoped_ptr(new IndexedDBKey(array
));
515 case kIndexedDBKeyBinaryTypeByte
: {
517 if (!DecodeBinary(slice
, &binary
))
519 *value
= make_scoped_ptr(new IndexedDBKey(binary
));
522 case kIndexedDBKeyStringTypeByte
: {
524 if (!DecodeStringWithLength(slice
, &s
))
526 *value
= make_scoped_ptr(new IndexedDBKey(s
));
529 case kIndexedDBKeyDateTypeByte
: {
531 if (!DecodeDouble(slice
, &d
))
533 *value
= make_scoped_ptr(new IndexedDBKey(d
, WebIDBKeyTypeDate
));
536 case kIndexedDBKeyNumberTypeByte
: {
538 if (!DecodeDouble(slice
, &d
))
540 *value
= make_scoped_ptr(new IndexedDBKey(d
, WebIDBKeyTypeNumber
));
549 bool DecodeDouble(StringPiece
* slice
, double* value
) {
550 if (slice
->size() < sizeof(*value
))
553 memcpy(value
, slice
->begin(), sizeof(*value
));
554 slice
->remove_prefix(sizeof(*value
));
558 bool DecodeIDBKeyPath(StringPiece
* slice
, IndexedDBKeyPath
* value
) {
559 // May be typed, or may be a raw string. An invalid leading
560 // byte sequence is used to identify typed coding. New records are
561 // always written as typed.
562 if (slice
->size() < 3 || (*slice
)[0] != kIndexedDBKeyPathTypeCodedByte1
||
563 (*slice
)[1] != kIndexedDBKeyPathTypeCodedByte2
) {
565 if (!DecodeString(slice
, &s
))
567 *value
= IndexedDBKeyPath(s
);
571 slice
->remove_prefix(2);
572 DCHECK(!slice
->empty());
573 WebIDBKeyPathType type
= static_cast<WebIDBKeyPathType
>((*slice
)[0]);
574 slice
->remove_prefix(1);
577 case WebIDBKeyPathTypeNull
:
578 DCHECK(slice
->empty());
579 *value
= IndexedDBKeyPath();
581 case WebIDBKeyPathTypeString
: {
582 base::string16 string
;
583 if (!DecodeStringWithLength(slice
, &string
))
585 DCHECK(slice
->empty());
586 *value
= IndexedDBKeyPath(string
);
589 case WebIDBKeyPathTypeArray
: {
590 std::vector
<base::string16
> array
;
592 if (!DecodeVarInt(slice
, &count
))
596 base::string16 string
;
597 if (!DecodeStringWithLength(slice
, &string
))
599 array
.push_back(string
);
601 DCHECK(slice
->empty());
602 *value
= IndexedDBKeyPath(array
);
610 bool ConsumeEncodedIDBKey(StringPiece
* slice
) {
611 unsigned char type
= (*slice
)[0];
612 slice
->remove_prefix(1);
615 case kIndexedDBKeyNullTypeByte
:
616 case kIndexedDBKeyMinKeyTypeByte
:
618 case kIndexedDBKeyArrayTypeByte
: {
620 if (!DecodeVarInt(slice
, &length
))
623 if (!ConsumeEncodedIDBKey(slice
))
628 case kIndexedDBKeyBinaryTypeByte
: {
630 if (!DecodeVarInt(slice
, &length
) || length
< 0)
632 if (slice
->size() < static_cast<size_t>(length
))
634 slice
->remove_prefix(length
);
637 case kIndexedDBKeyStringTypeByte
: {
639 if (!DecodeVarInt(slice
, &length
) || length
< 0)
641 if (slice
->size() < static_cast<size_t>(length
) * sizeof(base::char16
))
643 slice
->remove_prefix(length
* sizeof(base::char16
));
646 case kIndexedDBKeyDateTypeByte
:
647 case kIndexedDBKeyNumberTypeByte
:
648 if (slice
->size() < sizeof(double))
650 slice
->remove_prefix(sizeof(double));
657 bool ExtractEncodedIDBKey(StringPiece
* slice
, std::string
* result
) {
658 const char* start
= slice
->begin();
659 if (!ConsumeEncodedIDBKey(slice
))
663 result
->assign(start
, slice
->begin());
667 static WebIDBKeyType
KeyTypeByteToKeyType(unsigned char type
) {
669 case kIndexedDBKeyNullTypeByte
:
670 return WebIDBKeyTypeInvalid
;
671 case kIndexedDBKeyArrayTypeByte
:
672 return WebIDBKeyTypeArray
;
673 case kIndexedDBKeyBinaryTypeByte
:
674 return WebIDBKeyTypeBinary
;
675 case kIndexedDBKeyStringTypeByte
:
676 return WebIDBKeyTypeString
;
677 case kIndexedDBKeyDateTypeByte
:
678 return WebIDBKeyTypeDate
;
679 case kIndexedDBKeyNumberTypeByte
:
680 return WebIDBKeyTypeNumber
;
681 case kIndexedDBKeyMinKeyTypeByte
:
682 return WebIDBKeyTypeMin
;
686 return WebIDBKeyTypeInvalid
;
689 int CompareEncodedStringsWithLength(StringPiece
* slice1
,
693 if (!DecodeVarInt(slice1
, &len1
) || !DecodeVarInt(slice2
, &len2
)) {
699 if (len1
< 0 || len2
< 0) {
703 DCHECK_GE(slice1
->size(), len1
* sizeof(base::char16
));
704 DCHECK_GE(slice2
->size(), len2
* sizeof(base::char16
));
705 if (slice1
->size() < len1
* sizeof(base::char16
) ||
706 slice2
->size() < len2
* sizeof(base::char16
)) {
711 // Extract the string data, and advance the passed slices.
712 StringPiece
string1(slice1
->begin(), len1
* sizeof(base::char16
));
713 StringPiece
string2(slice2
->begin(), len2
* sizeof(base::char16
));
714 slice1
->remove_prefix(len1
* sizeof(base::char16
));
715 slice2
->remove_prefix(len2
* sizeof(base::char16
));
718 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
719 return string1
.compare(string2
);
722 int CompareEncodedBinary(StringPiece
* slice1
,
726 if (!DecodeVarInt(slice1
, &len1
) || !DecodeVarInt(slice2
, &len2
)) {
732 if (len1
< 0 || len2
< 0) {
739 DCHECK_GE(slice1
->size(), size1
);
740 DCHECK_GE(slice2
->size(), size2
);
741 if (slice1
->size() < size1
|| slice2
->size() < size2
) {
746 // Extract the binary data, and advance the passed slices.
747 StringPiece
binary1(slice1
->begin(), size1
);
748 StringPiece
binary2(slice2
->begin(), size2
);
749 slice1
->remove_prefix(size1
);
750 slice2
->remove_prefix(size2
);
753 // This is the same as a memcmp()
754 return binary1
.compare(binary2
);
757 static int CompareInts(int64 a
, int64 b
) {
759 // Exercised by unit tests in debug only.
771 static inline int CompareSizes(size_t a
, size_t b
) {
779 static int CompareTypes(WebIDBKeyType a
, WebIDBKeyType b
) { return b
- a
; }
781 int CompareEncodedIDBKeys(StringPiece
* slice_a
,
782 StringPiece
* slice_b
,
784 DCHECK(!slice_a
->empty());
785 DCHECK(!slice_b
->empty());
787 unsigned char type_a
= (*slice_a
)[0];
788 unsigned char type_b
= (*slice_b
)[0];
789 slice_a
->remove_prefix(1);
790 slice_b
->remove_prefix(1);
792 if (int x
= CompareTypes(KeyTypeByteToKeyType(type_a
),
793 KeyTypeByteToKeyType(type_b
)))
797 case kIndexedDBKeyNullTypeByte
:
798 case kIndexedDBKeyMinKeyTypeByte
:
799 // Null type or max type; no payload to compare.
801 case kIndexedDBKeyArrayTypeByte
: {
802 int64 length_a
, length_b
;
803 if (!DecodeVarInt(slice_a
, &length_a
) ||
804 !DecodeVarInt(slice_b
, &length_b
)) {
808 for (int64 i
= 0; i
< length_a
&& i
< length_b
; ++i
) {
809 int result
= CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
813 return length_a
- length_b
;
815 case kIndexedDBKeyBinaryTypeByte
:
816 return CompareEncodedBinary(slice_a
, slice_b
, ok
);
817 case kIndexedDBKeyStringTypeByte
:
818 return CompareEncodedStringsWithLength(slice_a
, slice_b
, ok
);
819 case kIndexedDBKeyDateTypeByte
:
820 case kIndexedDBKeyNumberTypeByte
: {
822 if (!DecodeDouble(slice_a
, &d
) || !DecodeDouble(slice_b
, &e
)) {
840 template <typename KeyType
>
841 int Compare(const StringPiece
& a
,
842 const StringPiece
& b
,
843 bool only_compare_index_keys
,
848 StringPiece
slice_a(a
);
849 if (!KeyType::Decode(&slice_a
, &key_a
)) {
853 StringPiece
slice_b(b
);
854 if (!KeyType::Decode(&slice_b
, &key_b
)) {
860 return key_a
.Compare(key_b
);
863 template <typename KeyType
>
864 int CompareSuffix(StringPiece
* a
,
866 bool only_compare_index_keys
,
873 int CompareSuffix
<ExistsEntryKey
>(StringPiece
* slice_a
,
874 StringPiece
* slice_b
,
875 bool only_compare_index_keys
,
877 DCHECK(!slice_a
->empty());
878 DCHECK(!slice_b
->empty());
879 return CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
883 int CompareSuffix
<ObjectStoreDataKey
>(StringPiece
* slice_a
,
884 StringPiece
* slice_b
,
885 bool only_compare_index_keys
,
887 return CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
891 int CompareSuffix
<BlobEntryKey
>(StringPiece
* slice_a
,
892 StringPiece
* slice_b
,
893 bool only_compare_index_keys
,
895 return CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
899 int CompareSuffix
<IndexDataKey
>(StringPiece
* slice_a
,
900 StringPiece
* slice_b
,
901 bool only_compare_index_keys
,
904 int result
= CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
907 if (only_compare_index_keys
)
910 // sequence number [optional]
911 int64 sequence_number_a
= -1;
912 int64 sequence_number_b
= -1;
913 if (!slice_a
->empty() && !DecodeVarInt(slice_a
, &sequence_number_a
))
915 if (!slice_b
->empty() && !DecodeVarInt(slice_b
, &sequence_number_b
))
918 if (slice_a
->empty() || slice_b
->empty())
919 return CompareSizes(slice_a
->size(), slice_b
->size());
921 // primary key [optional]
922 result
= CompareEncodedIDBKeys(slice_a
, slice_b
, ok
);
926 return CompareInts(sequence_number_a
, sequence_number_b
);
929 int Compare(const StringPiece
& a
,
930 const StringPiece
& b
,
931 bool only_compare_index_keys
,
933 StringPiece
slice_a(a
);
934 StringPiece
slice_b(b
);
937 bool ok_a
= KeyPrefix::Decode(&slice_a
, &prefix_a
);
938 bool ok_b
= KeyPrefix::Decode(&slice_b
, &prefix_b
);
941 if (!ok_a
|| !ok_b
) {
947 if (int x
= prefix_a
.Compare(prefix_b
))
950 switch (prefix_a
.type()) {
951 case KeyPrefix::GLOBAL_METADATA
: {
952 DCHECK(!slice_a
.empty());
953 DCHECK(!slice_b
.empty());
955 unsigned char type_byte_a
;
956 if (!DecodeByte(&slice_a
, &type_byte_a
)) {
961 unsigned char type_byte_b
;
962 if (!DecodeByte(&slice_b
, &type_byte_b
)) {
967 if (int x
= type_byte_a
- type_byte_b
)
969 if (type_byte_a
< kMaxSimpleGlobalMetaDataTypeByte
)
972 // Compare<> is used (which re-decodes the prefix) rather than an
973 // specialized CompareSuffix<> because metadata is relatively uncommon
976 if (type_byte_a
== kDatabaseFreeListTypeByte
) {
977 // TODO(jsbell): No need to pass only_compare_index_keys through here.
978 return Compare
<DatabaseFreeListKey
>(a
, b
, only_compare_index_keys
, ok
);
980 if (type_byte_a
== kDatabaseNameTypeByte
) {
981 return Compare
<DatabaseNameKey
>(
982 a
, b
, /*only_compare_index_keys*/ false, ok
);
987 case KeyPrefix::DATABASE_METADATA
: {
988 DCHECK(!slice_a
.empty());
989 DCHECK(!slice_b
.empty());
991 unsigned char type_byte_a
;
992 if (!DecodeByte(&slice_a
, &type_byte_a
)) {
997 unsigned char type_byte_b
;
998 if (!DecodeByte(&slice_b
, &type_byte_b
)) {
1003 if (int x
= type_byte_a
- type_byte_b
)
1005 if (type_byte_a
< DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE
)
1008 // Compare<> is used (which re-decodes the prefix) rather than an
1009 // specialized CompareSuffix<> because metadata is relatively uncommon
1012 if (type_byte_a
== kObjectStoreMetaDataTypeByte
) {
1013 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1014 return Compare
<ObjectStoreMetaDataKey
>(
1015 a
, b
, only_compare_index_keys
, ok
);
1017 if (type_byte_a
== kIndexMetaDataTypeByte
) {
1018 return Compare
<IndexMetaDataKey
>(
1019 a
, b
, /*only_compare_index_keys*/ false, ok
);
1021 if (type_byte_a
== kObjectStoreFreeListTypeByte
) {
1022 return Compare
<ObjectStoreFreeListKey
>(
1023 a
, b
, only_compare_index_keys
, ok
);
1025 if (type_byte_a
== kIndexFreeListTypeByte
) {
1026 return Compare
<IndexFreeListKey
>(
1027 a
, b
, /*only_compare_index_keys*/ false, ok
);
1029 if (type_byte_a
== kObjectStoreNamesTypeByte
) {
1030 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1031 return Compare
<ObjectStoreNamesKey
>(
1032 a
, b
, only_compare_index_keys
, ok
);
1034 if (type_byte_a
== kIndexNamesKeyTypeByte
) {
1035 return Compare
<IndexNamesKey
>(
1036 a
, b
, /*only_compare_index_keys*/ false, ok
);
1041 case KeyPrefix::OBJECT_STORE_DATA
: {
1042 // Provide a stable ordering for invalid data.
1043 if (slice_a
.empty() || slice_b
.empty())
1044 return CompareSizes(slice_a
.size(), slice_b
.size());
1046 return CompareSuffix
<ObjectStoreDataKey
>(
1047 &slice_a
, &slice_b
, /*only_compare_index_keys*/ false, ok
);
1050 case KeyPrefix::EXISTS_ENTRY
: {
1051 // Provide a stable ordering for invalid data.
1052 if (slice_a
.empty() || slice_b
.empty())
1053 return CompareSizes(slice_a
.size(), slice_b
.size());
1055 return CompareSuffix
<ExistsEntryKey
>(
1056 &slice_a
, &slice_b
, /*only_compare_index_keys*/ false, ok
);
1059 case KeyPrefix::BLOB_ENTRY
: {
1060 // Provide a stable ordering for invalid data.
1061 if (slice_a
.empty() || slice_b
.empty())
1062 return CompareSizes(slice_a
.size(), slice_b
.size());
1064 return CompareSuffix
<BlobEntryKey
>(
1065 &slice_a
, &slice_b
, /*only_compare_index_keys*/ false, ok
);
1068 case KeyPrefix::INDEX_DATA
: {
1069 // Provide a stable ordering for invalid data.
1070 if (slice_a
.empty() || slice_b
.empty())
1071 return CompareSizes(slice_a
.size(), slice_b
.size());
1073 return CompareSuffix
<IndexDataKey
>(
1074 &slice_a
, &slice_b
, only_compare_index_keys
, ok
);
1077 case KeyPrefix::INVALID_TYPE
:
1088 int Compare(const StringPiece
& a
,
1089 const StringPiece
& b
,
1090 bool only_compare_index_keys
) {
1092 int result
= Compare(a
, b
, only_compare_index_keys
, &ok
);
1099 KeyPrefix::KeyPrefix()
1100 : database_id_(INVALID_TYPE
),
1101 object_store_id_(INVALID_TYPE
),
1102 index_id_(INVALID_TYPE
) {}
1104 KeyPrefix::KeyPrefix(int64 database_id
)
1105 : database_id_(database_id
), object_store_id_(0), index_id_(0) {
1106 DCHECK(KeyPrefix::IsValidDatabaseId(database_id
));
1109 KeyPrefix::KeyPrefix(int64 database_id
, int64 object_store_id
)
1110 : database_id_(database_id
),
1111 object_store_id_(object_store_id
),
1113 DCHECK(KeyPrefix::IsValidDatabaseId(database_id
));
1114 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id
));
1117 KeyPrefix::KeyPrefix(int64 database_id
, int64 object_store_id
, int64 index_id
)
1118 : database_id_(database_id
),
1119 object_store_id_(object_store_id
),
1120 index_id_(index_id
) {
1121 DCHECK(KeyPrefix::IsValidDatabaseId(database_id
));
1122 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id
));
1123 DCHECK(KeyPrefix::IsValidIndexId(index_id
));
1126 KeyPrefix::KeyPrefix(enum Type type
,
1128 int64 object_store_id
,
1130 : database_id_(database_id
),
1131 object_store_id_(object_store_id
),
1132 index_id_(index_id
) {
1133 DCHECK_EQ(type
, INVALID_TYPE
);
1134 DCHECK(KeyPrefix::IsValidDatabaseId(database_id
));
1135 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id
));
1138 KeyPrefix
KeyPrefix::CreateWithSpecialIndex(int64 database_id
,
1139 int64 object_store_id
,
1141 DCHECK(KeyPrefix::IsValidDatabaseId(database_id
));
1142 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id
));
1144 return KeyPrefix(INVALID_TYPE
, database_id
, object_store_id
, index_id
);
1147 bool KeyPrefix::IsValidDatabaseId(int64 database_id
) {
1148 return (database_id
> 0) && (database_id
< KeyPrefix::kMaxDatabaseId
);
1151 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id
) {
1152 return (object_store_id
> 0) &&
1153 (object_store_id
< KeyPrefix::kMaxObjectStoreId
);
1156 bool KeyPrefix::IsValidIndexId(int64 index_id
) {
1157 return (index_id
>= kMinimumIndexId
) && (index_id
< KeyPrefix::kMaxIndexId
);
1160 bool KeyPrefix::Decode(StringPiece
* slice
, KeyPrefix
* result
) {
1161 unsigned char first_byte
;
1162 if (!DecodeByte(slice
, &first_byte
))
1165 size_t database_id_bytes
= ((first_byte
>> 5) & 0x7) + 1;
1166 size_t object_store_id_bytes
= ((first_byte
>> 2) & 0x7) + 1;
1167 size_t index_id_bytes
= (first_byte
& 0x3) + 1;
1169 if (database_id_bytes
+ object_store_id_bytes
+ index_id_bytes
>
1174 StringPiece
tmp(slice
->begin(), database_id_bytes
);
1175 if (!DecodeInt(&tmp
, &result
->database_id_
))
1178 slice
->remove_prefix(database_id_bytes
);
1180 StringPiece
tmp(slice
->begin(), object_store_id_bytes
);
1181 if (!DecodeInt(&tmp
, &result
->object_store_id_
))
1184 slice
->remove_prefix(object_store_id_bytes
);
1186 StringPiece
tmp(slice
->begin(), index_id_bytes
);
1187 if (!DecodeInt(&tmp
, &result
->index_id_
))
1190 slice
->remove_prefix(index_id_bytes
);
1194 std::string
KeyPrefix::EncodeEmpty() {
1195 const std::string
result(4, 0);
1196 DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1200 std::string
KeyPrefix::Encode() const {
1201 DCHECK(database_id_
!= kInvalidId
);
1202 DCHECK(object_store_id_
!= kInvalidId
);
1203 DCHECK(index_id_
!= kInvalidId
);
1204 return EncodeInternal(database_id_
, object_store_id_
, index_id_
);
1207 std::string
KeyPrefix::EncodeInternal(int64 database_id
,
1208 int64 object_store_id
,
1210 std::string database_id_string
;
1211 std::string object_store_id_string
;
1212 std::string index_id_string
;
1214 EncodeIntSafely(database_id
, kMaxDatabaseId
, &database_id_string
);
1215 EncodeIntSafely(object_store_id
, kMaxObjectStoreId
, &object_store_id_string
);
1216 EncodeIntSafely(index_id
, kMaxIndexId
, &index_id_string
);
1218 DCHECK(database_id_string
.size() <= kMaxDatabaseIdSizeBytes
);
1219 DCHECK(object_store_id_string
.size() <= kMaxObjectStoreIdSizeBytes
);
1220 DCHECK(index_id_string
.size() <= kMaxIndexIdSizeBytes
);
1222 unsigned char first_byte
=
1223 (database_id_string
.size() - 1) << (kMaxObjectStoreIdSizeBits
+
1224 kMaxIndexIdSizeBits
) |
1225 (object_store_id_string
.size() - 1) << kMaxIndexIdSizeBits
|
1226 (index_id_string
.size() - 1);
1227 COMPILE_ASSERT(kMaxDatabaseIdSizeBits
+ kMaxObjectStoreIdSizeBits
+
1228 kMaxIndexIdSizeBits
==
1229 sizeof(first_byte
) * 8,
1232 ret
.reserve(kDefaultInlineBufferSize
);
1233 ret
.push_back(first_byte
);
1234 ret
.append(database_id_string
);
1235 ret
.append(object_store_id_string
);
1236 ret
.append(index_id_string
);
1238 DCHECK_LE(ret
.size(), kDefaultInlineBufferSize
);
1242 int KeyPrefix::Compare(const KeyPrefix
& other
) const {
1243 DCHECK(database_id_
!= kInvalidId
);
1244 DCHECK(object_store_id_
!= kInvalidId
);
1245 DCHECK(index_id_
!= kInvalidId
);
1247 if (database_id_
!= other
.database_id_
)
1248 return CompareInts(database_id_
, other
.database_id_
);
1249 if (object_store_id_
!= other
.object_store_id_
)
1250 return CompareInts(object_store_id_
, other
.object_store_id_
);
1251 if (index_id_
!= other
.index_id_
)
1252 return CompareInts(index_id_
, other
.index_id_
);
1256 KeyPrefix::Type
KeyPrefix::type() const {
1257 DCHECK(database_id_
!= kInvalidId
);
1258 DCHECK(object_store_id_
!= kInvalidId
);
1259 DCHECK(index_id_
!= kInvalidId
);
1262 return GLOBAL_METADATA
;
1263 if (!object_store_id_
)
1264 return DATABASE_METADATA
;
1265 if (index_id_
== kObjectStoreDataIndexId
)
1266 return OBJECT_STORE_DATA
;
1267 if (index_id_
== kExistsEntryIndexId
)
1268 return EXISTS_ENTRY
;
1269 if (index_id_
== kBlobEntryIndexId
)
1271 if (index_id_
>= kMinimumIndexId
)
1275 return INVALID_TYPE
;
1278 std::string
SchemaVersionKey::Encode() {
1279 std::string ret
= KeyPrefix::EncodeEmpty();
1280 ret
.push_back(kSchemaVersionTypeByte
);
1284 std::string
MaxDatabaseIdKey::Encode() {
1285 std::string ret
= KeyPrefix::EncodeEmpty();
1286 ret
.push_back(kMaxDatabaseIdTypeByte
);
1290 std::string
DataVersionKey::Encode() {
1291 std::string ret
= KeyPrefix::EncodeEmpty();
1292 ret
.push_back(kDataVersionTypeByte
);
1296 std::string
BlobJournalKey::Encode() {
1297 std::string ret
= KeyPrefix::EncodeEmpty();
1298 ret
.push_back(kBlobJournalTypeByte
);
1302 std::string
LiveBlobJournalKey::Encode() {
1303 std::string ret
= KeyPrefix::EncodeEmpty();
1304 ret
.push_back(kLiveBlobJournalTypeByte
);
1308 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1310 bool DatabaseFreeListKey::Decode(StringPiece
* slice
,
1311 DatabaseFreeListKey
* result
) {
1313 if (!KeyPrefix::Decode(slice
, &prefix
))
1315 DCHECK(!prefix
.database_id_
);
1316 DCHECK(!prefix
.object_store_id_
);
1317 DCHECK(!prefix
.index_id_
);
1318 unsigned char type_byte
= 0;
1319 if (!DecodeByte(slice
, &type_byte
))
1321 DCHECK_EQ(type_byte
, kDatabaseFreeListTypeByte
);
1322 if (!DecodeVarInt(slice
, &result
->database_id_
))
1327 std::string
DatabaseFreeListKey::Encode(int64 database_id
) {
1328 std::string ret
= KeyPrefix::EncodeEmpty();
1329 ret
.push_back(kDatabaseFreeListTypeByte
);
1330 EncodeVarInt(database_id
, &ret
);
1334 std::string
DatabaseFreeListKey::EncodeMaxKey() {
1335 return Encode(std::numeric_limits
<int64
>::max());
1338 int64
DatabaseFreeListKey::DatabaseId() const {
1339 DCHECK_GE(database_id_
, 0);
1340 return database_id_
;
1343 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey
& other
) const {
1344 DCHECK_GE(database_id_
, 0);
1345 return CompareInts(database_id_
, other
.database_id_
);
1348 bool DatabaseNameKey::Decode(StringPiece
* slice
, DatabaseNameKey
* result
) {
1350 if (!KeyPrefix::Decode(slice
, &prefix
))
1352 DCHECK(!prefix
.database_id_
);
1353 DCHECK(!prefix
.object_store_id_
);
1354 DCHECK(!prefix
.index_id_
);
1355 unsigned char type_byte
= 0;
1356 if (!DecodeByte(slice
, &type_byte
))
1358 DCHECK_EQ(type_byte
, kDatabaseNameTypeByte
);
1359 if (!DecodeStringWithLength(slice
, &result
->origin_
))
1361 if (!DecodeStringWithLength(slice
, &result
->database_name_
))
1366 std::string
DatabaseNameKey::Encode(const std::string
& origin_identifier
,
1367 const base::string16
& database_name
) {
1368 std::string ret
= KeyPrefix::EncodeEmpty();
1369 ret
.push_back(kDatabaseNameTypeByte
);
1370 EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier
), &ret
);
1371 EncodeStringWithLength(database_name
, &ret
);
1375 std::string
DatabaseNameKey::EncodeMinKeyForOrigin(
1376 const std::string
& origin_identifier
) {
1377 return Encode(origin_identifier
, base::string16());
1380 std::string
DatabaseNameKey::EncodeStopKeyForOrigin(
1381 const std::string
& origin_identifier
) {
1382 // just after origin in collation order
1383 return EncodeMinKeyForOrigin(origin_identifier
+ '\x01');
1386 int DatabaseNameKey::Compare(const DatabaseNameKey
& other
) {
1387 if (int x
= origin_
.compare(other
.origin_
))
1389 return database_name_
.compare(other
.database_name_
);
1392 bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key
) {
1393 return blob_key
>= kBlobKeyGeneratorInitialNumber
;
1396 const int64
DatabaseMetaDataKey::kAllBlobsKey
= 1;
1397 const int64
DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber
= 2;
1398 const int64
DatabaseMetaDataKey::kInvalidBlobKey
= -1;
1400 std::string
DatabaseMetaDataKey::Encode(int64 database_id
,
1401 MetaDataType meta_data_type
) {
1402 KeyPrefix
prefix(database_id
);
1403 std::string ret
= prefix
.Encode();
1404 ret
.push_back(meta_data_type
);
1408 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1409 : object_store_id_(-1), meta_data_type_(-1) {}
1411 bool ObjectStoreMetaDataKey::Decode(StringPiece
* slice
,
1412 ObjectStoreMetaDataKey
* result
) {
1414 if (!KeyPrefix::Decode(slice
, &prefix
))
1416 DCHECK(prefix
.database_id_
);
1417 DCHECK(!prefix
.object_store_id_
);
1418 DCHECK(!prefix
.index_id_
);
1419 unsigned char type_byte
= 0;
1420 if (!DecodeByte(slice
, &type_byte
))
1422 DCHECK_EQ(type_byte
, kObjectStoreMetaDataTypeByte
);
1423 if (!DecodeVarInt(slice
, &result
->object_store_id_
))
1425 DCHECK(result
->object_store_id_
);
1426 if (!DecodeByte(slice
, &result
->meta_data_type_
))
1431 std::string
ObjectStoreMetaDataKey::Encode(int64 database_id
,
1432 int64 object_store_id
,
1433 unsigned char meta_data_type
) {
1434 KeyPrefix
prefix(database_id
);
1435 std::string ret
= prefix
.Encode();
1436 ret
.push_back(kObjectStoreMetaDataTypeByte
);
1437 EncodeVarInt(object_store_id
, &ret
);
1438 ret
.push_back(meta_data_type
);
1442 std::string
ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id
) {
1443 return Encode(database_id
,
1444 std::numeric_limits
<int64
>::max(),
1445 kObjectMetaDataTypeMaximum
);
1448 std::string
ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id
,
1449 int64 object_store_id
) {
1450 return Encode(database_id
, object_store_id
, kObjectMetaDataTypeMaximum
);
1453 int64
ObjectStoreMetaDataKey::ObjectStoreId() const {
1454 DCHECK_GE(object_store_id_
, 0);
1455 return object_store_id_
;
1457 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1458 return meta_data_type_
;
1461 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey
& other
) {
1462 DCHECK_GE(object_store_id_
, 0);
1463 if (int x
= CompareInts(object_store_id_
, other
.object_store_id_
))
1465 return meta_data_type_
- other
.meta_data_type_
;
1468 IndexMetaDataKey::IndexMetaDataKey()
1469 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1471 bool IndexMetaDataKey::Decode(StringPiece
* slice
, IndexMetaDataKey
* result
) {
1473 if (!KeyPrefix::Decode(slice
, &prefix
))
1475 DCHECK(prefix
.database_id_
);
1476 DCHECK(!prefix
.object_store_id_
);
1477 DCHECK(!prefix
.index_id_
);
1478 unsigned char type_byte
= 0;
1479 if (!DecodeByte(slice
, &type_byte
))
1481 DCHECK_EQ(type_byte
, kIndexMetaDataTypeByte
);
1482 if (!DecodeVarInt(slice
, &result
->object_store_id_
))
1484 if (!DecodeVarInt(slice
, &result
->index_id_
))
1486 if (!DecodeByte(slice
, &result
->meta_data_type_
))
1491 std::string
IndexMetaDataKey::Encode(int64 database_id
,
1492 int64 object_store_id
,
1494 unsigned char meta_data_type
) {
1495 KeyPrefix
prefix(database_id
);
1496 std::string ret
= prefix
.Encode();
1497 ret
.push_back(kIndexMetaDataTypeByte
);
1498 EncodeVarInt(object_store_id
, &ret
);
1499 EncodeVarInt(index_id
, &ret
);
1500 EncodeByte(meta_data_type
, &ret
);
1504 std::string
IndexMetaDataKey::EncodeMaxKey(int64 database_id
,
1505 int64 object_store_id
) {
1506 return Encode(database_id
,
1508 std::numeric_limits
<int64
>::max(),
1509 kIndexMetaDataTypeMaximum
);
1512 std::string
IndexMetaDataKey::EncodeMaxKey(int64 database_id
,
1513 int64 object_store_id
,
1516 database_id
, object_store_id
, index_id
, kIndexMetaDataTypeMaximum
);
1519 int IndexMetaDataKey::Compare(const IndexMetaDataKey
& other
) {
1520 DCHECK_GE(object_store_id_
, 0);
1521 DCHECK_GE(index_id_
, 0);
1523 if (int x
= CompareInts(object_store_id_
, other
.object_store_id_
))
1525 if (int x
= CompareInts(index_id_
, other
.index_id_
))
1527 return meta_data_type_
- other
.meta_data_type_
;
1530 int64
IndexMetaDataKey::IndexId() const {
1531 DCHECK_GE(index_id_
, 0);
1535 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1537 bool ObjectStoreFreeListKey::Decode(StringPiece
* slice
,
1538 ObjectStoreFreeListKey
* result
) {
1540 if (!KeyPrefix::Decode(slice
, &prefix
))
1542 DCHECK(prefix
.database_id_
);
1543 DCHECK(!prefix
.object_store_id_
);
1544 DCHECK(!prefix
.index_id_
);
1545 unsigned char type_byte
= 0;
1546 if (!DecodeByte(slice
, &type_byte
))
1548 DCHECK_EQ(type_byte
, kObjectStoreFreeListTypeByte
);
1549 if (!DecodeVarInt(slice
, &result
->object_store_id_
))
1554 std::string
ObjectStoreFreeListKey::Encode(int64 database_id
,
1555 int64 object_store_id
) {
1556 KeyPrefix
prefix(database_id
);
1557 std::string ret
= prefix
.Encode();
1558 ret
.push_back(kObjectStoreFreeListTypeByte
);
1559 EncodeVarInt(object_store_id
, &ret
);
1563 std::string
ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id
) {
1564 return Encode(database_id
, std::numeric_limits
<int64
>::max());
1567 int64
ObjectStoreFreeListKey::ObjectStoreId() const {
1568 DCHECK_GE(object_store_id_
, 0);
1569 return object_store_id_
;
1572 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey
& other
) {
1573 // TODO(jsbell): It may seem strange that we're not comparing database id's,
1574 // but that comparison will have been made earlier.
1575 // We should probably make this more clear, though...
1576 DCHECK_GE(object_store_id_
, 0);
1577 return CompareInts(object_store_id_
, other
.object_store_id_
);
1580 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1582 bool IndexFreeListKey::Decode(StringPiece
* slice
, IndexFreeListKey
* result
) {
1584 if (!KeyPrefix::Decode(slice
, &prefix
))
1586 DCHECK(prefix
.database_id_
);
1587 DCHECK(!prefix
.object_store_id_
);
1588 DCHECK(!prefix
.index_id_
);
1589 unsigned char type_byte
= 0;
1590 if (!DecodeByte(slice
, &type_byte
))
1592 DCHECK_EQ(type_byte
, kIndexFreeListTypeByte
);
1593 if (!DecodeVarInt(slice
, &result
->object_store_id_
))
1595 if (!DecodeVarInt(slice
, &result
->index_id_
))
1600 std::string
IndexFreeListKey::Encode(int64 database_id
,
1601 int64 object_store_id
,
1603 KeyPrefix
prefix(database_id
);
1604 std::string ret
= prefix
.Encode();
1605 ret
.push_back(kIndexFreeListTypeByte
);
1606 EncodeVarInt(object_store_id
, &ret
);
1607 EncodeVarInt(index_id
, &ret
);
1611 std::string
IndexFreeListKey::EncodeMaxKey(int64 database_id
,
1612 int64 object_store_id
) {
1614 database_id
, object_store_id
, std::numeric_limits
<int64
>::max());
1617 int IndexFreeListKey::Compare(const IndexFreeListKey
& other
) {
1618 DCHECK_GE(object_store_id_
, 0);
1619 DCHECK_GE(index_id_
, 0);
1620 if (int x
= CompareInts(object_store_id_
, other
.object_store_id_
))
1622 return CompareInts(index_id_
, other
.index_id_
);
1625 int64
IndexFreeListKey::ObjectStoreId() const {
1626 DCHECK_GE(object_store_id_
, 0);
1627 return object_store_id_
;
1630 int64
IndexFreeListKey::IndexId() const {
1631 DCHECK_GE(index_id_
, 0);
1635 // TODO(jsbell): We never use this to look up object store ids,
1636 // because a mapping is kept in the IndexedDBDatabase. Can the
1637 // mapping become unreliable? Can we remove this?
1638 bool ObjectStoreNamesKey::Decode(StringPiece
* slice
,
1639 ObjectStoreNamesKey
* result
) {
1641 if (!KeyPrefix::Decode(slice
, &prefix
))
1643 DCHECK(prefix
.database_id_
);
1644 DCHECK(!prefix
.object_store_id_
);
1645 DCHECK(!prefix
.index_id_
);
1646 unsigned char type_byte
= 0;
1647 if (!DecodeByte(slice
, &type_byte
))
1649 DCHECK_EQ(type_byte
, kObjectStoreNamesTypeByte
);
1650 if (!DecodeStringWithLength(slice
, &result
->object_store_name_
))
1655 std::string
ObjectStoreNamesKey::Encode(
1657 const base::string16
& object_store_name
) {
1658 KeyPrefix
prefix(database_id
);
1659 std::string ret
= prefix
.Encode();
1660 ret
.push_back(kObjectStoreNamesTypeByte
);
1661 EncodeStringWithLength(object_store_name
, &ret
);
1665 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey
& other
) {
1666 return object_store_name_
.compare(other
.object_store_name_
);
1669 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1671 // TODO(jsbell): We never use this to look up index ids, because a mapping
1672 // is kept at a higher level.
1673 bool IndexNamesKey::Decode(StringPiece
* slice
, IndexNamesKey
* result
) {
1675 if (!KeyPrefix::Decode(slice
, &prefix
))
1677 DCHECK(prefix
.database_id_
);
1678 DCHECK(!prefix
.object_store_id_
);
1679 DCHECK(!prefix
.index_id_
);
1680 unsigned char type_byte
= 0;
1681 if (!DecodeByte(slice
, &type_byte
))
1683 DCHECK_EQ(type_byte
, kIndexNamesKeyTypeByte
);
1684 if (!DecodeVarInt(slice
, &result
->object_store_id_
))
1686 if (!DecodeStringWithLength(slice
, &result
->index_name_
))
1691 std::string
IndexNamesKey::Encode(int64 database_id
,
1692 int64 object_store_id
,
1693 const base::string16
& index_name
) {
1694 KeyPrefix
prefix(database_id
);
1695 std::string ret
= prefix
.Encode();
1696 ret
.push_back(kIndexNamesKeyTypeByte
);
1697 EncodeVarInt(object_store_id
, &ret
);
1698 EncodeStringWithLength(index_name
, &ret
);
1702 int IndexNamesKey::Compare(const IndexNamesKey
& other
) {
1703 DCHECK_GE(object_store_id_
, 0);
1704 if (int x
= CompareInts(object_store_id_
, other
.object_store_id_
))
1706 return index_name_
.compare(other
.index_name_
);
1709 ObjectStoreDataKey::ObjectStoreDataKey() {}
1710 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1712 bool ObjectStoreDataKey::Decode(StringPiece
* slice
,
1713 ObjectStoreDataKey
* result
) {
1715 if (!KeyPrefix::Decode(slice
, &prefix
))
1717 DCHECK(prefix
.database_id_
);
1718 DCHECK(prefix
.object_store_id_
);
1719 DCHECK_EQ(prefix
.index_id_
, kSpecialIndexNumber
);
1720 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_user_key_
))
1725 std::string
ObjectStoreDataKey::Encode(int64 database_id
,
1726 int64 object_store_id
,
1727 const std::string encoded_user_key
) {
1728 KeyPrefix
prefix(KeyPrefix::CreateWithSpecialIndex(
1729 database_id
, object_store_id
, kSpecialIndexNumber
));
1730 std::string ret
= prefix
.Encode();
1731 ret
.append(encoded_user_key
);
1736 std::string
ObjectStoreDataKey::Encode(int64 database_id
,
1737 int64 object_store_id
,
1738 const IndexedDBKey
& user_key
) {
1739 std::string encoded_key
;
1740 EncodeIDBKey(user_key
, &encoded_key
);
1741 return Encode(database_id
, object_store_id
, encoded_key
);
1744 scoped_ptr
<IndexedDBKey
> ObjectStoreDataKey::user_key() const {
1745 scoped_ptr
<IndexedDBKey
> key
;
1746 StringPiece
slice(encoded_user_key_
);
1747 if (!DecodeIDBKey(&slice
, &key
)) {
1748 // TODO(jsbell): Return error.
1753 const int64
ObjectStoreDataKey::kSpecialIndexNumber
= kObjectStoreDataIndexId
;
1755 ExistsEntryKey::ExistsEntryKey() {}
1756 ExistsEntryKey::~ExistsEntryKey() {}
1758 bool ExistsEntryKey::Decode(StringPiece
* slice
, ExistsEntryKey
* result
) {
1760 if (!KeyPrefix::Decode(slice
, &prefix
))
1762 DCHECK(prefix
.database_id_
);
1763 DCHECK(prefix
.object_store_id_
);
1764 DCHECK_EQ(prefix
.index_id_
, kSpecialIndexNumber
);
1765 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_user_key_
))
1770 std::string
ExistsEntryKey::Encode(int64 database_id
,
1771 int64 object_store_id
,
1772 const std::string
& encoded_key
) {
1773 KeyPrefix
prefix(KeyPrefix::CreateWithSpecialIndex(
1774 database_id
, object_store_id
, kSpecialIndexNumber
));
1775 std::string ret
= prefix
.Encode();
1776 ret
.append(encoded_key
);
1780 std::string
ExistsEntryKey::Encode(int64 database_id
,
1781 int64 object_store_id
,
1782 const IndexedDBKey
& user_key
) {
1783 std::string encoded_key
;
1784 EncodeIDBKey(user_key
, &encoded_key
);
1785 return Encode(database_id
, object_store_id
, encoded_key
);
1788 scoped_ptr
<IndexedDBKey
> ExistsEntryKey::user_key() const {
1789 scoped_ptr
<IndexedDBKey
> key
;
1790 StringPiece
slice(encoded_user_key_
);
1791 if (!DecodeIDBKey(&slice
, &key
)) {
1792 // TODO(jsbell): Return error.
1797 const int64
ExistsEntryKey::kSpecialIndexNumber
= kExistsEntryIndexId
;
1799 bool BlobEntryKey::Decode(StringPiece
* slice
, BlobEntryKey
* result
) {
1801 if (!KeyPrefix::Decode(slice
, &prefix
))
1803 DCHECK(prefix
.database_id_
);
1804 DCHECK(prefix
.object_store_id_
);
1805 DCHECK_EQ(prefix
.index_id_
, kSpecialIndexNumber
);
1807 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_user_key_
))
1809 result
->database_id_
= prefix
.database_id_
;
1810 result
->object_store_id_
= prefix
.object_store_id_
;
1815 bool BlobEntryKey::FromObjectStoreDataKey(StringPiece
* slice
,
1816 BlobEntryKey
* result
) {
1818 if (!KeyPrefix::Decode(slice
, &prefix
))
1820 DCHECK(prefix
.database_id_
);
1821 DCHECK(prefix
.object_store_id_
);
1822 DCHECK_EQ(prefix
.index_id_
, ObjectStoreDataKey::kSpecialIndexNumber
);
1824 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_user_key_
))
1826 result
->database_id_
= prefix
.database_id_
;
1827 result
->object_store_id_
= prefix
.object_store_id_
;
1831 std::string
BlobEntryKey::ReencodeToObjectStoreDataKey(StringPiece
* slice
) {
1832 // TODO(ericu): We could be more efficient here, since the suffix is the same.
1834 if (!Decode(slice
, &key
))
1835 return std::string();
1837 return ObjectStoreDataKey::Encode(
1838 key
.database_id_
, key
.object_store_id_
, key
.encoded_user_key_
);
1841 std::string
BlobEntryKey::EncodeMinKeyForObjectStore(int64 database_id
,
1842 int64 object_store_id
) {
1843 // Our implied encoded_user_key_ here is empty, the lowest possible key.
1844 return Encode(database_id
, object_store_id
, std::string());
1847 std::string
BlobEntryKey::EncodeStopKeyForObjectStore(int64 database_id
,
1848 int64 object_store_id
) {
1849 DCHECK(KeyPrefix::ValidIds(database_id
, object_store_id
));
1850 KeyPrefix
prefix(KeyPrefix::CreateWithSpecialIndex(
1851 database_id
, object_store_id
, kSpecialIndexNumber
+ 1));
1852 return prefix
.Encode();
1855 std::string
BlobEntryKey::Encode() const {
1856 DCHECK(!encoded_user_key_
.empty());
1857 return Encode(database_id_
, object_store_id_
, encoded_user_key_
);
1860 std::string
BlobEntryKey::Encode(int64 database_id
,
1861 int64 object_store_id
,
1862 const IndexedDBKey
& user_key
) {
1863 std::string encoded_key
;
1864 EncodeIDBKey(user_key
, &encoded_key
);
1865 return Encode(database_id
, object_store_id
, encoded_key
);
1868 std::string
BlobEntryKey::Encode(int64 database_id
,
1869 int64 object_store_id
,
1870 const std::string
& encoded_user_key
) {
1871 DCHECK(KeyPrefix::ValidIds(database_id
, object_store_id
));
1872 KeyPrefix
prefix(KeyPrefix::CreateWithSpecialIndex(
1873 database_id
, object_store_id
, kSpecialIndexNumber
));
1874 return prefix
.Encode() + encoded_user_key
;
1877 const int64
BlobEntryKey::kSpecialIndexNumber
= kBlobEntryIndexId
;
1879 IndexDataKey::IndexDataKey()
1881 object_store_id_(-1),
1883 sequence_number_(-1) {}
1885 IndexDataKey::~IndexDataKey() {}
1887 bool IndexDataKey::Decode(StringPiece
* slice
, IndexDataKey
* result
) {
1889 if (!KeyPrefix::Decode(slice
, &prefix
))
1891 DCHECK(prefix
.database_id_
);
1892 DCHECK(prefix
.object_store_id_
);
1893 DCHECK_GE(prefix
.index_id_
, kMinimumIndexId
);
1894 result
->database_id_
= prefix
.database_id_
;
1895 result
->object_store_id_
= prefix
.object_store_id_
;
1896 result
->index_id_
= prefix
.index_id_
;
1897 result
->sequence_number_
= -1;
1898 result
->encoded_primary_key_
= MinIDBKey();
1900 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_user_key_
))
1903 // [optional] sequence number
1906 if (!DecodeVarInt(slice
, &result
->sequence_number_
))
1909 // [optional] primary key
1912 if (!ExtractEncodedIDBKey(slice
, &result
->encoded_primary_key_
))
1917 std::string
IndexDataKey::Encode(int64 database_id
,
1918 int64 object_store_id
,
1920 const std::string
& encoded_user_key
,
1921 const std::string
& encoded_primary_key
,
1922 int64 sequence_number
) {
1923 KeyPrefix
prefix(database_id
, object_store_id
, index_id
);
1924 std::string ret
= prefix
.Encode();
1925 ret
.append(encoded_user_key
);
1926 EncodeVarInt(sequence_number
, &ret
);
1927 ret
.append(encoded_primary_key
);
1931 std::string
IndexDataKey::Encode(int64 database_id
,
1932 int64 object_store_id
,
1934 const IndexedDBKey
& user_key
) {
1935 std::string encoded_key
;
1936 EncodeIDBKey(user_key
, &encoded_key
);
1938 database_id
, object_store_id
, index_id
, encoded_key
, MinIDBKey(), 0);
1941 std::string
IndexDataKey::Encode(int64 database_id
,
1942 int64 object_store_id
,
1944 const IndexedDBKey
& user_key
,
1945 const IndexedDBKey
& user_primary_key
) {
1946 std::string encoded_key
;
1947 EncodeIDBKey(user_key
, &encoded_key
);
1948 std::string encoded_primary_key
;
1949 EncodeIDBKey(user_primary_key
, &encoded_primary_key
);
1950 return Encode(database_id
,
1954 encoded_primary_key
,
1958 std::string
IndexDataKey::EncodeMinKey(int64 database_id
,
1959 int64 object_store_id
,
1962 database_id
, object_store_id
, index_id
, MinIDBKey(), MinIDBKey(), 0);
1965 std::string
IndexDataKey::EncodeMaxKey(int64 database_id
,
1966 int64 object_store_id
,
1968 return Encode(database_id
,
1973 std::numeric_limits
<int64
>::max());
1976 int64
IndexDataKey::DatabaseId() const {
1977 DCHECK_GE(database_id_
, 0);
1978 return database_id_
;
1981 int64
IndexDataKey::ObjectStoreId() const {
1982 DCHECK_GE(object_store_id_
, 0);
1983 return object_store_id_
;
1986 int64
IndexDataKey::IndexId() const {
1987 DCHECK_GE(index_id_
, 0);
1991 scoped_ptr
<IndexedDBKey
> IndexDataKey::user_key() const {
1992 scoped_ptr
<IndexedDBKey
> key
;
1993 StringPiece
slice(encoded_user_key_
);
1994 if (!DecodeIDBKey(&slice
, &key
)) {
1995 // TODO(jsbell): Return error.
2000 scoped_ptr
<IndexedDBKey
> IndexDataKey::primary_key() const {
2001 scoped_ptr
<IndexedDBKey
> key
;
2002 StringPiece
slice(encoded_primary_key_
);
2003 if (!DecodeIDBKey(&slice
, &key
)) {
2004 // TODO(jsbell): Return error.
2009 } // namespace content