1use std::{cmp::Ordering, collections::Bound};
5
6use reifydb_codec::{
7 key::{
8 ByteSink,
9 deserializer::KeyDeserializer,
10 encoded::{EncodedKey, EncodedKeyRange},
11 serializer::KeySerializer,
12 },
13 row::shape::fingerprint::RowShapeFingerprint,
14};
15use reifydb_macro::KeyCodec;
16use reifydb_value::value::{partition::Partition, row_number::RowNumber};
17use serde::{Deserialize, Serialize};
18
19use super::{KeyRangeCodec, KeyTag};
20use crate::{
21 interface::catalog::{object::ObjectId, storage::StorageId},
22 key::{
23 any::{Field, KeyFields, RawEncoding, TaggedKey, Width},
24 bound::{TaggedKeyBoundRange, object_fields},
25 catalog::{KeyDeserializerCatalogExt, KeySerializerCatalogExt},
26 sort_run::SortRun,
27 typed::{
28 BoundedKey, DenseKey,
29 direction::{Asc, Desc},
30 },
31 },
32 metrics::heap::HeapSize,
33};
34
35#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
36#[key(tag = Row)]
37pub struct RowKey {
38 pub storage: StorageId,
39 pub row: RowNumber,
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub struct RowKeyRange {
44 pub storage: StorageId,
45}
46
47impl RowKeyRange {
48 fn decode_key(key: &EncodedKey) -> Option<Self> {
49 let mut de = KeyDeserializer::from_bytes(key.as_slice());
50
51 let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
52 if kind != Self::TAG {
53 return None;
54 }
55
56 let storage = StorageId::from_object(de.read_object_id().ok()?)?;
57
58 Some(RowKeyRange {
59 storage,
60 })
61 }
62
63 pub fn storage_scan(storage: StorageId) -> TaggedKeyBoundRange {
64 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage)))
65 }
66
67 pub fn scan_range(storage: StorageId, last: Option<&TaggedKey>) -> TaggedKeyBoundRange {
68 Self::storage_scan(storage).resume_after(last)
69 }
70
71 pub fn scan_range_rev(storage: StorageId, last: Option<&TaggedKey>) -> TaggedKeyBoundRange {
72 Self::storage_scan(storage).resume_before(last)
73 }
74}
75
76impl KeyRangeCodec for RowKeyRange {
77 const TAG: KeyTag = KeyTag::Row;
78
79 fn start(&self) -> Option<EncodedKey> {
80 let mut serializer = KeySerializer::with_capacity(10);
81 serializer.extend_u8(Self::TAG as u8).extend_object_id(self.storage);
82 Some(serializer.to_encoded_key())
83 }
84
85 fn end(&self) -> Option<EncodedKey> {
86 let mut serializer = KeySerializer::with_capacity(10);
87 serializer.extend_u8(Self::TAG as u8).extend_object_id(ObjectId::from(self.storage).prev());
88 Some(serializer.to_encoded_key())
89 }
90
91 fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
92 where
93 Self: Sized,
94 {
95 let start_key = match &range.start {
96 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
97 Bound::Unbounded => None,
98 };
99
100 let end_key = match &range.end {
101 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
102 Bound::Unbounded => None,
103 };
104
105 (start_key, end_key)
106 }
107}
108
109impl RowKey {
110 pub fn new(storage: impl Into<StorageId>, row: impl Into<RowNumber>) -> Self {
111 Self {
112 storage: storage.into(),
113 row: row.into(),
114 }
115 }
116
117 pub fn encoded(storage: impl Into<StorageId>, row: impl Into<RowNumber>) -> EncodedKey {
118 Self {
119 storage: storage.into(),
120 row: row.into(),
121 }
122 .encode()
123 }
124
125 pub fn full_scan(storage: impl Into<StorageId>) -> TaggedKeyBoundRange {
126 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage.into())))
127 }
128
129 pub fn storage_start(storage: impl Into<StorageId>) -> EncodedKey {
130 let mut serializer = KeySerializer::with_capacity(10);
131 serializer.extend_u8(RowKey::TAG as u8).extend_object_id(storage.into());
132 serializer.to_encoded_key()
133 }
134
135 pub fn storage_end(storage: impl Into<StorageId>) -> EncodedKey {
136 let mut serializer = KeySerializer::with_capacity(10);
137 serializer.extend_u8(RowKey::TAG as u8).extend_object_id(ObjectId::from(storage.into()).prev());
138 serializer.to_encoded_key()
139 }
140}
141
142#[derive(Debug, Clone, PartialEq, KeyCodec, Eq, Hash)]
143#[key(tag = SortedViewRow)]
144pub struct SortedViewRowKey {
145 pub storage: StorageId,
146 pub run: SortRun,
147 pub row: Asc<RowNumber>,
148}
149
150impl Ord for SortedViewRowKey {
151 fn cmp(&self, other: &Self) -> Ordering {
152 storage_order(self.storage)
153 .cmp(&storage_order(other.storage))
154 .then_with(|| self.run.cmp(&other.run))
155 .then_with(|| self.row.cmp(&other.row))
156 }
157}
158
159impl PartialOrd for SortedViewRowKey {
160 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
161 Some(self.cmp(other))
162 }
163}
164
165impl SortedViewRowKey {
166 pub fn new(storage: impl Into<StorageId>, run: SortRun, row: RowNumber) -> Self {
167 Self {
168 storage: storage.into(),
169 run,
170 row: Asc(row),
171 }
172 }
173
174 pub fn encoded(storage: impl Into<StorageId>, run: SortRun, row: RowNumber) -> EncodedKey {
175 Self::new(storage, run, row).encode()
176 }
177
178 pub fn storage_start(storage: impl Into<StorageId>) -> EncodedKey {
179 let mut serializer = KeySerializer::with_capacity(10);
180 serializer.extend_u8(Self::TAG as u8).extend_object_id(storage.into());
181 serializer.to_encoded_key()
182 }
183
184 pub fn storage_scan(storage: impl Into<StorageId>) -> TaggedKeyBoundRange {
185 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage.into())))
186 }
187
188 pub fn scan_range(storage: impl Into<StorageId>, last: Option<&TaggedKey>) -> TaggedKeyBoundRange {
189 Self::storage_scan(storage).resume_after(last)
190 }
191
192 pub fn storage_of(key: &EncodedKey) -> Option<StorageId> {
193 let mut de = KeyDeserializer::from_bytes(key.as_slice());
194 let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
195 if kind != Self::TAG {
196 return None;
197 }
198 StorageId::from_object(de.read_object_id().ok()?)
199 }
200
201 pub fn row_of(key: &EncodedKey) -> Option<RowNumber> {
202 let bytes = key.as_slice();
203 if KeyTag::of(bytes)? != Self::TAG {
204 return None;
205 }
206 let tail = bytes.len().checked_sub(8)?;
207 Some(RowNumber(u64::from_be_bytes(bytes[tail..].try_into().ok()?)))
208 }
209
210 pub fn range_storage_of(range: &EncodedKeyRange) -> Option<StorageId> {
211 let start = bound_storage_of(&range.start, Self::TAG)?;
212 bound_storage_of(&range.end, Self::TAG)?;
213 Some(start)
214 }
215}
216
217const SORT_RUN_MARKER: u8 = 0x00;
218const SORT_RUN_ZERO: u8 = 0xff;
219const SORT_RUN_END: u8 = 0x00;
220
221pub(crate) fn encode_sort_run<B: ByteSink>(run: &[u8], out: &mut B) {
222 for &byte in run {
223 if byte == SORT_RUN_MARKER {
224 out.extend_from_slice(&[SORT_RUN_MARKER, SORT_RUN_ZERO]);
225 } else {
226 out.push(byte);
227 }
228 }
229 out.extend_from_slice(&[SORT_RUN_MARKER, SORT_RUN_END]);
230}
231
232fn extend_sort_run(serializer: &mut KeySerializer, run: &SortRun) {
233 encode_sort_run(run.as_slice(), serializer);
234}
235
236fn read_sort_run(de: &mut KeyDeserializer) -> Option<SortRun> {
237 let mut run: Vec<u8> = Vec::new();
238 loop {
239 let byte = de.read_raw(1).ok()?[0];
240 if byte != SORT_RUN_MARKER {
241 run.push(byte);
242 continue;
243 }
244 match de.read_raw(1).ok()?[0] {
245 SORT_RUN_END => return Some(SortRun::new(run)),
246 SORT_RUN_ZERO => run.push(0x00),
247 _ => return None,
248 }
249 }
250}
251
252fn read_row_tail(de: &mut KeyDeserializer) -> Option<Asc<RowNumber>> {
253 let bytes: [u8; 8] = de.read_raw(8).ok()?.try_into().ok()?;
254 Some(Asc(RowNumber(u64::from_be_bytes(bytes))))
255}
256
257fn storage_order(storage: StorageId) -> (u8, Desc<u64>) {
258 (ObjectId::from(storage).type_tag(), Desc(storage.as_u64()))
259}
260
261fn bound_storage_of(bound: &Bound<EncodedKey>, kind: KeyTag) -> Option<StorageId> {
262 let key = match bound {
263 Bound::Included(key) | Bound::Excluded(key) => key,
264 Bound::Unbounded => return None,
265 };
266 let mut de = KeyDeserializer::from_bytes(key.as_slice());
267 if KeyTag::try_from(de.read_u8().ok()?).ok()? != kind {
268 return None;
269 }
270 StorageId::from_object(de.read_object_id().ok()?)
271}
272
273#[derive(Debug, Clone, PartialEq, KeyCodec, Eq, Hash)]
274#[key(tag = PartitionedSortedViewRow)]
275pub struct PartitionedSortedViewRowKey {
276 pub storage: StorageId,
277 pub partition: Partition,
278 pub run: SortRun,
279 pub row: Asc<RowNumber>,
280}
281
282impl Ord for PartitionedSortedViewRowKey {
283 fn cmp(&self, other: &Self) -> Ordering {
284 storage_order(self.storage)
285 .cmp(&storage_order(other.storage))
286 .then_with(|| Desc(self.partition).cmp(&Desc(other.partition)))
287 .then_with(|| self.run.cmp(&other.run))
288 .then_with(|| self.row.cmp(&other.row))
289 }
290}
291
292impl PartialOrd for PartitionedSortedViewRowKey {
293 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
294 Some(self.cmp(other))
295 }
296}
297
298impl PartitionedSortedViewRowKey {
299 pub fn new(storage: impl Into<StorageId>, partition: Partition, run: SortRun, row: RowNumber) -> Self {
300 Self {
301 storage: storage.into(),
302 partition,
303 run,
304 row: Asc(row),
305 }
306 }
307
308 pub fn encoded(
309 storage: impl Into<StorageId>,
310 partition: Partition,
311 run: SortRun,
312 row: RowNumber,
313 ) -> EncodedKey {
314 Self::new(storage, partition, run, row).encode()
315 }
316
317 pub fn storage_start(storage: impl Into<StorageId>) -> EncodedKey {
318 let mut serializer = KeySerializer::with_capacity(10);
319 serializer.extend_u8(Self::TAG as u8).extend_object_id(storage.into());
320 serializer.to_encoded_key()
321 }
322
323 pub fn storage_scan(storage: impl Into<StorageId>) -> TaggedKeyBoundRange {
324 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage.into())))
325 }
326
327 pub fn scan_range(storage: impl Into<StorageId>, last: Option<&TaggedKey>) -> TaggedKeyBoundRange {
328 Self::storage_scan(storage).resume_after(last)
329 }
330
331 pub fn partition_range(storage: impl Into<StorageId>, partition: Partition) -> TaggedKeyBoundRange {
332 TaggedKeyBoundRange::prefix(
333 Self::TAG,
334 object_fields(ObjectId::from(storage.into()))
335 .into_iter()
336 .chain([Field::UDesc(Width::U128, partition.0)])
337 .collect::<Vec<_>>(),
338 )
339 }
340
341 pub fn partition_scan_range(
342 storage: impl Into<StorageId>,
343 partition: Partition,
344 last: Option<&TaggedKey>,
345 ) -> TaggedKeyBoundRange {
346 Self::partition_range(storage, partition).resume_after(last)
347 }
348
349 pub fn storage_of(key: &EncodedKey) -> Option<StorageId> {
350 let mut de = KeyDeserializer::from_bytes(key.as_slice());
351 let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
352 if kind != Self::TAG {
353 return None;
354 }
355 StorageId::from_object(de.read_object_id().ok()?)
356 }
357
358 pub fn row_of(key: &EncodedKey) -> Option<RowNumber> {
359 let bytes = key.as_slice();
360 if KeyTag::of(bytes)? != Self::TAG {
361 return None;
362 }
363 let tail = bytes.len().checked_sub(8)?;
364 Some(RowNumber(u64::from_be_bytes(bytes[tail..].try_into().ok()?)))
365 }
366
367 pub fn range_storage_of(range: &EncodedKeyRange) -> Option<StorageId> {
368 let start = bound_storage_of(&range.start, Self::TAG)?;
369 bound_storage_of(&range.end, Self::TAG)?;
370 Some(start)
371 }
372}
373
374#[cfg(test)]
375#[allow(clippy::disallowed_methods)]
376mod sorted_view_row_key_tests {
377 use std::ops::RangeBounds;
378
379 use reifydb_codec::key::encoded::EncodedKey;
380 use reifydb_value::value::{Value, partition::Partition, row_number::RowNumber};
381
382 use super::{PartitionedSortedViewRowKey, RowKey, SortedViewRowKey, TaggedKey};
383 use crate::{interface::catalog::storage::StorageId, key::sort_run::SortRun};
384
385 fn part(v: &str) -> Partition {
386 Partition::of(&[Value::Utf8(v.to_string())])
387 }
388
389 fn sorted_view(storage: StorageId, sort: &[u8], row: RowNumber) -> EncodedKey {
390 SortedViewRowKey::encoded(storage, SortRun::new(sort), row)
391 }
392
393 fn sorted_view_cursor(storage: StorageId, sort: &[u8], row: RowNumber) -> TaggedKey {
394 TaggedKey::from(SortedViewRowKey::new(storage, SortRun::new(sort), row))
395 }
396
397 fn partitioned(storage: StorageId, partition: Partition, sort: &[u8], row: RowNumber) -> EncodedKey {
398 PartitionedSortedViewRowKey::encoded(storage, partition, SortRun::new(sort), row)
399 }
400
401 #[test]
402 fn test_row_comes_from_the_tail_not_the_sort_prefix() {
403 let storage = StorageId::view(3);
406 let a = sorted_view(storage, &[0xAA; 8], RowNumber(7));
407 let b = sorted_view(storage, &[0xBB; 24], RowNumber(9));
408
409 assert_eq!(SortedViewRowKey::row_of(&a), Some(RowNumber(7)));
410 assert_eq!(SortedViewRowKey::row_of(&b), Some(RowNumber(9)));
411 assert_eq!(SortedViewRowKey::storage_of(&a), Some(storage));
412 }
413
414 #[test]
415 fn test_row_of_rejects_a_plain_row_key() {
416 let plain = RowKey::encoded(StorageId::view(3), RowNumber(7));
419 assert_eq!(SortedViewRowKey::row_of(&plain), None);
420 assert_eq!(PartitionedSortedViewRowKey::row_of(&plain), None);
421 }
422
423 #[test]
424 fn test_scan_range_covers_its_storage_and_nothing_else() {
425 let storage = StorageId::view(3);
426 let range = SortedViewRowKey::scan_range(storage, None).encode();
427
428 assert!(range.contains(&sorted_view(storage, &[0x00; 8], RowNumber(1))));
429 assert!(range.contains(&sorted_view(storage, &[0xFF; 8], RowNumber(u64::MAX))));
430 assert!(!range.contains(&sorted_view(StorageId::view(4), &[0x00; 8], RowNumber(1))));
431 }
432
433 #[test]
434 fn test_scan_range_resumes_strictly_after_the_last_key() {
435 let storage = StorageId::view(3);
437 let last = sorted_view_cursor(storage, &[0x40; 8], RowNumber(5));
438 let range = SortedViewRowKey::scan_range(storage, Some(&last)).encode();
439
440 assert!(!range.contains(&last.encode()));
441 assert!(range.contains(&sorted_view(storage, &[0x41; 8], RowNumber(1))));
442 }
443
444 #[test]
445 fn test_sort_prefix_orders_the_keyspace() {
446 let storage = StorageId::view(3);
449 let early_sort_late_row = sorted_view(storage, &[0x10; 8], RowNumber(999));
450 let late_sort_early_row = sorted_view(storage, &[0x20; 8], RowNumber(1));
451
452 assert!(early_sort_late_row < late_sort_early_row);
453 }
454
455 #[test]
456 fn test_partition_range_contains_only_its_partition() {
457 let storage = StorageId::view(3);
458 let range = PartitionedSortedViewRowKey::partition_range(storage, part("us")).encode();
459
460 assert!(range.contains(&partitioned(storage, part("us"), &[0x10; 8], RowNumber(1))));
461 assert!(!range.contains(&partitioned(storage, part("eu"), &[0x10; 8], RowNumber(1))));
462 }
463
464 #[test]
465 fn test_partitioned_row_comes_from_the_tail() {
466 let storage = StorageId::view(3);
467 let key = partitioned(storage, part("us"), &[0xAA; 8], RowNumber(42));
468
469 assert_eq!(PartitionedSortedViewRowKey::row_of(&key), Some(RowNumber(42)));
470 assert_eq!(PartitionedSortedViewRowKey::storage_of(&key), Some(storage));
471 assert_eq!(SortedViewRowKey::row_of(&key), None);
472 }
473}
474
475#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
476pub struct StorageRowKey(pub Desc<RowNumber>);
477
478impl From<RowKey> for StorageRowKey {
479 fn from(key: RowKey) -> Self {
480 StorageRowKey::new(key.row)
481 }
482}
483
484impl StorageRowKey {
485 pub fn new(row: RowNumber) -> Self {
486 StorageRowKey(Desc(row))
487 }
488
489 pub fn row(self) -> RowNumber {
490 self.0.0
491 }
492
493 pub fn with_storage(self, storage: StorageId) -> RowKey {
494 RowKey {
495 storage,
496 row: self.row(),
497 }
498 }
499}
500
501impl HeapSize for StorageRowKey {
502 fn heap_size(&self) -> usize {
503 0
504 }
505}
506
507impl BoundedKey for StorageRowKey {
508 fn low() -> Self {
509 StorageRowKey(<Desc<RowNumber> as BoundedKey>::low())
510 }
511}
512
513impl DenseKey for StorageRowKey {
514 fn successor(&self) -> Option<Self> {
515 self.0.successor().map(StorageRowKey)
516 }
517}
518
519#[cfg(test)]
520pub mod row_key_tests {
521 use reifydb_value::value::row_number::RowNumber;
522
523 use super::{RowKey, StorageRowKey};
524 use crate::{
525 interface::catalog::storage::StorageId,
526 key::typed::{BoundedKey, DenseKey},
527 };
528
529 #[test]
530 fn test_encode_decode() {
531 let key = RowKey {
532 storage: StorageId::table(0xABCD),
533 row: RowNumber(0x123456789ABCDEF0),
534 };
535 let encoded = key.encode();
536
537 let expected: Vec<u8> = vec![
538 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, 0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43,
539 0x21, 0x0F,
540 ];
541
542 assert_eq!(encoded.as_slice(), expected);
543
544 let key = RowKey::decode(&encoded).unwrap();
545 assert_eq!(key.storage, StorageId::table(0xABCD));
546 assert_eq!(key.row, 0x123456789ABCDEF0);
547 }
548
549 #[test]
550 fn test_encode_decode_view() {
551 let key = RowKey {
553 storage: StorageId::view(0xABCD),
554 row: RowNumber(0x123456789ABCDEF0),
555 };
556 let encoded = key.encode();
557
558 let expected: Vec<u8> = vec![
559 0xFC, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, 0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43,
560 0x21, 0x0F,
561 ];
562
563 assert_eq!(encoded.as_slice(), expected);
564
565 let key = RowKey::decode(&encoded).unwrap();
566 assert_eq!(key.storage, StorageId::view(0xABCD));
567 assert_eq!(key.row, 0x123456789ABCDEF0);
568 }
569
570 #[test]
571 fn test_order_preserving() {
572 let key1 = RowKey {
573 storage: StorageId::table(1),
574 row: RowNumber(100),
575 };
576 let key2 = RowKey {
577 storage: StorageId::table(1),
578 row: RowNumber(200),
579 };
580 let key3 = RowKey {
581 storage: StorageId::table(2),
582 row: RowNumber(1),
583 };
584
585 let encoded1 = key1.encode();
586 let encoded2 = key2.encode();
587 let encoded3 = key3.encode();
588
589 assert!(encoded3 < encoded2, "ordering not preserved");
590 assert!(encoded2 < encoded1, "ordering not preserved");
591 }
592
593 #[test]
594 fn test_row_ident_roundtrip() {
595 let key = RowKey {
596 storage: StorageId::table(7),
597 row: RowNumber(42),
598 };
599
600 let ident: StorageRowKey = key.clone().into();
602 let restored = ident.with_storage(key.storage);
603 assert_eq!(restored, key);
604 }
605
606 #[test]
607 fn test_row_ident_ordering_matches_the_encoded_key() {
608 let storage = StorageId::table(1);
609 let one = StorageRowKey::new(RowNumber(1));
610 let two = StorageRowKey::new(RowNumber(2));
611
612 assert!(two < one);
615 assert_eq!(
616 two < one,
617 RowKey::encoded(storage, RowNumber(2)).as_slice()
618 < RowKey::encoded(storage, RowNumber(1)).as_slice()
619 );
620 }
621
622 #[test]
623 fn test_row_ident_low_is_the_greatest_row() {
624 assert_eq!(<StorageRowKey as BoundedKey>::low(), StorageRowKey::new(RowNumber(u64::MAX)));
627 }
628
629 #[test]
630 fn test_row_ident_successor_is_the_next_key_in_scan_order() {
631 let ident = StorageRowKey::new(RowNumber(5));
633 let next = ident.successor().unwrap();
634 assert_eq!(next, StorageRowKey::new(RowNumber(4)));
635 assert!(next > ident);
636 assert!(StorageRowKey::new(RowNumber(3)) > next);
637 }
638
639 #[test]
640 fn test_row_ident_successor_runs_out_at_row_zero() {
641 assert_eq!(StorageRowKey::new(RowNumber(0)).successor(), None);
643 }
644}
645
646#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
647#[key(tag = RowSequence)]
648pub struct RowSequenceKey {
649 pub storage: StorageId,
650}
651
652impl RowSequenceKey {
653 pub fn new(storage: StorageId) -> Self {
654 Self {
655 storage,
656 }
657 }
658
659 pub fn encoded(storage: impl Into<StorageId>) -> EncodedKey {
660 Self::new(storage.into()).encode()
661 }
662
663 pub fn full_scan() -> TaggedKeyBoundRange {
664 TaggedKeyBoundRange::kind(Self::TAG)
665 }
666}
667
668#[cfg(test)]
669pub mod row_sequence_key_tests {
670 use super::RowSequenceKey;
671 use crate::interface::catalog::storage::StorageId;
672
673 #[test]
674 fn test_encode_decode() {
675 let key = RowSequenceKey {
676 storage: StorageId::table(0xABCD),
677 };
678 let encoded = key.encode();
679 let expected = vec![0xF7, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32];
680 assert_eq!(encoded.as_slice(), expected);
681
682 let key = RowSequenceKey::decode(&encoded).unwrap();
683 assert_eq!(key.storage, StorageId::table(0xABCD));
684 }
685
686 #[test]
687 fn test_encode_decode_view() {
688 let key = RowSequenceKey {
690 storage: StorageId::view(0xABCD),
691 };
692 let encoded = key.encode();
693 let expected = vec![0xF7, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32];
694 assert_eq!(encoded.as_slice(), expected);
695
696 let key = RowSequenceKey::decode(&encoded).unwrap();
697 assert_eq!(key.storage, StorageId::view(0xABCD));
698 }
699}
700
701#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, KeyCodec, Hash)]
702#[key(tag = RowSettings)]
703pub struct RowSettingsKey {
704 pub storage: StorageId,
705}
706
707impl RowSettingsKey {
708 pub fn new(storage: StorageId) -> Self {
709 Self {
710 storage,
711 }
712 }
713
714 pub fn encoded(storage: StorageId) -> EncodedKey {
715 Self::new(storage).encode()
716 }
717
718 pub fn full_scan() -> TaggedKeyBoundRange {
719 TaggedKeyBoundRange::kind(Self::TAG)
720 }
721}
722
723#[cfg(test)]
724pub mod row_settings_key_tests {
725 use super::*;
726 use crate::interface::catalog::id::{RingBufferId, SeriesId, TableId, ViewId};
727
728 #[test]
729 fn test_row_settings_key_encoding() {
730 let key = RowSettingsKey {
731 storage: StorageId::Table(TableId(42)),
732 };
733
734 let encoded = key.encode();
735 let decoded = RowSettingsKey::decode(&encoded).unwrap();
736 assert_eq!(key, decoded);
737 }
738
739 #[test]
740 fn test_row_settings_key_roundtrip_view() {
741 let key = RowSettingsKey {
743 storage: StorageId::View(ViewId(13)),
744 };
745
746 let encoded = key.encode();
747 let decoded = RowSettingsKey::decode(&encoded).unwrap();
748 assert_eq!(key, decoded);
749 }
750
751 #[test]
752 fn test_row_settings_key_roundtrip_ringbuffer() {
753 let key = RowSettingsKey {
754 storage: StorageId::RingBuffer(RingBufferId(99)),
755 };
756
757 let encoded = key.encode();
758 let decoded = RowSettingsKey::decode(&encoded).unwrap();
759 assert_eq!(key, decoded);
760 }
761
762 #[test]
763 fn test_row_settings_key_roundtrip_series() {
764 let key = RowSettingsKey {
765 storage: StorageId::Series(SeriesId(7)),
766 };
767
768 let encoded = key.encode();
769 let decoded = RowSettingsKey::decode(&encoded).unwrap();
770 assert_eq!(key, decoded);
771 }
772}
773
774#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
775#[key(tag = RowShape)]
776pub struct RowShapeKey {
777 pub fingerprint: RowShapeFingerprint,
778}
779
780impl RowShapeKey {
781 pub fn new(fingerprint: RowShapeFingerprint) -> Self {
782 Self {
783 fingerprint,
784 }
785 }
786
787 pub fn encoded(fingerprint: RowShapeFingerprint) -> EncodedKey {
788 Self {
789 fingerprint,
790 }
791 .encode()
792 }
793
794 pub fn full_scan() -> TaggedKeyBoundRange {
795 TaggedKeyBoundRange::kind(Self::TAG)
796 }
797}
798
799#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
800#[key(tag = RowShapeField)]
801pub struct RowShapeFieldKey {
802 pub shape_fingerprint: RowShapeFingerprint,
803 pub field_index: u16,
804}
805
806impl RowShapeFieldKey {
807 pub fn new(shape_fingerprint: RowShapeFingerprint, field_index: u16) -> Self {
808 Self {
809 shape_fingerprint,
810 field_index,
811 }
812 }
813
814 pub fn encoded(shape_fingerprint: RowShapeFingerprint, field_index: u16) -> EncodedKey {
815 Self::new(shape_fingerprint, field_index).encode()
816 }
817}
818
819#[cfg(test)]
820mod row_shape_key_tests {
821 use super::*;
822
823 #[test]
824 fn test_shape_key_encode_decode() {
825 let key = RowShapeKey {
826 fingerprint: RowShapeFingerprint::new(0xDEADBEEFCAFEBABE),
827 };
828 let encoded = key.encode();
829 let decoded = RowShapeKey::decode(&encoded).unwrap();
830 assert_eq!(decoded.fingerprint, RowShapeFingerprint::new(0xDEADBEEFCAFEBABE));
831 }
832
833 #[test]
834 fn test_shape_field_key_encode_decode() {
835 let key = RowShapeFieldKey {
836 shape_fingerprint: RowShapeFingerprint::new(0x1234567890ABCDEF),
837 field_index: 42,
838 };
839 let encoded = key.encode();
840 let decoded = RowShapeFieldKey::decode(&encoded).unwrap();
841 assert_eq!(decoded.shape_fingerprint, RowShapeFingerprint::new(0x1234567890ABCDEF));
842 assert_eq!(decoded.field_index, 42);
843 }
844}
845
846#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
847#[key(tag = PartitionedRow)]
848pub struct PartitionedRowKey {
849 pub storage: StorageId,
850 pub partition: Partition,
851 pub row: RowNumber,
852}
853
854impl PartitionedRowKey {
855 pub fn new(storage: impl Into<StorageId>, partition: Partition, row: RowNumber) -> Self {
856 Self {
857 storage: storage.into(),
858 partition,
859 row,
860 }
861 }
862
863 pub fn encoded(storage: impl Into<StorageId>, partition: Partition, row: RowNumber) -> EncodedKey {
864 Self::new(storage, partition, row).encode()
865 }
866
867 pub fn storage_start(storage: impl Into<StorageId>) -> EncodedKey {
868 let mut serializer = KeySerializer::with_capacity(10);
869 serializer.extend_u8(PartitionedRowKey::TAG as u8).extend_object_id(storage.into());
870 serializer.to_encoded_key()
871 }
872
873 pub fn storage_end(storage: impl Into<StorageId>) -> EncodedKey {
874 let mut serializer = KeySerializer::with_capacity(10);
875 serializer
876 .extend_u8(PartitionedRowKey::TAG as u8)
877 .extend_object_id(ObjectId::from(storage.into()).prev());
878 serializer.to_encoded_key()
879 }
880
881 pub fn storage_of(key: &EncodedKey) -> Option<StorageId> {
882 let mut de = KeyDeserializer::from_bytes(key.as_slice());
883 let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
884 if kind != Self::TAG {
885 return None;
886 }
887 StorageId::from_object(de.read_object_id().ok()?)
888 }
889
890 pub fn full_scan(storage: impl Into<StorageId>) -> TaggedKeyBoundRange {
891 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage.into())))
892 }
893
894 pub fn scan_range(storage: impl Into<StorageId>, last: Option<&TaggedKey>) -> TaggedKeyBoundRange {
895 Self::full_scan(storage).resume_after(last)
896 }
897
898 pub fn partition_range(storage: impl Into<StorageId>, partition: Partition) -> TaggedKeyBoundRange {
899 TaggedKeyBoundRange::prefix(
900 Self::TAG,
901 object_fields(ObjectId::from(storage.into()))
902 .into_iter()
903 .chain([Field::UDesc(Width::U128, partition.0)])
904 .collect::<Vec<_>>(),
905 )
906 }
907
908 pub fn partition_scan_range(
909 storage: impl Into<StorageId>,
910 partition: Partition,
911 last: Option<&TaggedKey>,
912 ) -> TaggedKeyBoundRange {
913 Self::partition_range(storage, partition).resume_after(last)
914 }
915}
916
917#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
918pub struct StoragePartitionedRowKey {
919 pub partition: Desc<Partition>,
920 pub row: Desc<RowNumber>,
921}
922
923impl StoragePartitionedRowKey {
924 pub fn new(partition: Partition, row: RowNumber) -> Self {
925 Self {
926 partition: Desc(partition),
927 row: Desc(row),
928 }
929 }
930
931 pub fn partition(self) -> Partition {
932 self.partition.0
933 }
934
935 pub fn row(self) -> RowNumber {
936 self.row.0
937 }
938
939 pub fn partition_hi(self) -> u64 {
940 (self.partition().0 >> 64) as u64
941 }
942
943 pub fn partition_lo(self) -> u64 {
944 self.partition().0 as u64
945 }
946
947 pub fn from_halves(partition_hi: u64, partition_lo: u64, row: RowNumber) -> Self {
948 Self::new(Partition(((partition_hi as u128) << 64) | partition_lo as u128), row)
949 }
950
951 pub fn with_storage(self, storage: StorageId) -> PartitionedRowKey {
952 PartitionedRowKey {
953 storage,
954 partition: self.partition(),
955 row: self.row(),
956 }
957 }
958}
959
960impl From<PartitionedRowKey> for StoragePartitionedRowKey {
961 fn from(key: PartitionedRowKey) -> Self {
962 StoragePartitionedRowKey::new(key.partition, key.row)
963 }
964}
965
966impl HeapSize for StoragePartitionedRowKey {
967 fn heap_size(&self) -> usize {
968 0
969 }
970}
971
972impl BoundedKey for StoragePartitionedRowKey {
973 fn low() -> Self {
974 Self {
975 partition: <Desc<Partition> as BoundedKey>::low(),
976 row: <Desc<RowNumber> as BoundedKey>::low(),
977 }
978 }
979}
980
981impl DenseKey for StoragePartitionedRowKey {
982 fn successor(&self) -> Option<Self> {
983 if let Some(row) = self.row.successor() {
984 return Some(Self {
985 partition: self.partition,
986 row,
987 });
988 }
989 Some(Self {
990 partition: self.partition.successor()?,
991 row: <Desc<RowNumber> as BoundedKey>::low(),
992 })
993 }
994}
995
996#[derive(Debug, Clone, PartialEq)]
997pub struct PartitionedRowKeyRange {
998 pub storage: StorageId,
999}
1000
1001impl PartitionedRowKeyRange {
1002 fn decode_key(key: &EncodedKey) -> Option<Self> {
1003 let mut de = KeyDeserializer::from_bytes(key.as_slice());
1004
1005 let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1006 if kind != Self::TAG {
1007 return None;
1008 }
1009
1010 let storage = StorageId::from_object(de.read_object_id().ok()?)?;
1011
1012 Some(PartitionedRowKeyRange {
1013 storage,
1014 })
1015 }
1016}
1017
1018impl KeyRangeCodec for PartitionedRowKeyRange {
1019 const TAG: KeyTag = KeyTag::PartitionedRow;
1020
1021 fn start(&self) -> Option<EncodedKey> {
1022 let mut serializer = KeySerializer::with_capacity(10);
1023 serializer.extend_u8(Self::TAG as u8).extend_object_id(self.storage);
1024 Some(serializer.to_encoded_key())
1025 }
1026
1027 fn end(&self) -> Option<EncodedKey> {
1028 let mut serializer = KeySerializer::with_capacity(10);
1029 serializer.extend_u8(Self::TAG as u8).extend_object_id(ObjectId::from(self.storage).prev());
1030 Some(serializer.to_encoded_key())
1031 }
1032
1033 fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
1034 where
1035 Self: Sized,
1036 {
1037 let start_key = match &range.start {
1038 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
1039 Bound::Unbounded => None,
1040 };
1041
1042 let end_key = match &range.end {
1043 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
1044 Bound::Unbounded => None,
1045 };
1046
1047 (start_key, end_key)
1048 }
1049}
1050
1051#[cfg(test)]
1052#[allow(clippy::disallowed_methods)]
1053mod partitioned_row_key_tests {
1054 use std::ops::RangeBounds;
1055
1056 use reifydb_codec::key::{encoded::EncodedKey, serializer::KeySerializer};
1057 use reifydb_value::value::{Value, partition::Partition, row_number::RowNumber};
1058
1059 use super::{PartitionedRowKey, RowKey, StoragePartitionedRowKey};
1060 use crate::{
1061 interface::catalog::{
1062 id::{TableId, ViewId},
1063 object::ObjectId,
1064 storage::StorageId,
1065 },
1066 key::{
1067 catalog::KeySerializerCatalogExt,
1068 typed::{BoundedKey, DenseKey},
1069 },
1070 };
1071
1072 fn part(v: &str) -> Partition {
1073 Partition::of(&[Value::Utf8(v.to_string())])
1074 }
1075
1076 #[test]
1077 fn test_table_roundtrip() {
1078 let key = PartitionedRowKey {
1079 storage: StorageId::Table(TableId(7)),
1080 partition: part("us"),
1081 row: RowNumber(42),
1082 };
1083 let decoded = PartitionedRowKey::decode(&key.encode()).unwrap();
1084 assert_eq!(decoded, key);
1085 }
1086
1087 #[test]
1088 fn test_view_roundtrip() {
1089 let key = PartitionedRowKey {
1091 storage: StorageId::View(ViewId(11)),
1092 partition: part("us"),
1093 row: RowNumber(42),
1094 };
1095 let decoded = PartitionedRowKey::decode(&key.encode()).unwrap();
1096 assert_eq!(decoded, key);
1097 }
1098
1099 #[test]
1100 fn test_storage_of() {
1101 let key = PartitionedRowKey::encoded(StorageId::Table(TableId(42)), part("us"), RowNumber(1));
1102 assert_eq!(PartitionedRowKey::storage_of(&key), Some(StorageId::Table(TableId(42))));
1103 }
1104
1105 #[test]
1106 fn test_storage_of_rejects_a_rowless_object() {
1107 let mut serializer = KeySerializer::with_capacity(10);
1109 serializer.extend_u8(PartitionedRowKey::TAG as u8).extend_object_id(ObjectId::vtable(42));
1110 assert_eq!(PartitionedRowKey::storage_of(&serializer.to_encoded_key()), None);
1111 }
1112
1113 #[test]
1114 fn test_partition_rows_cluster_together() {
1115 let storage = StorageId::Table(TableId(1));
1116 let us_a = PartitionedRowKey::encoded(storage, part("us"), RowNumber(1));
1117 let us_b = PartitionedRowKey::encoded(storage, part("us"), RowNumber(2));
1118 let eu = PartitionedRowKey::encoded(storage, part("eu"), RowNumber(1));
1119
1120 let mut keys = [us_a.clone(), us_b.clone(), eu.clone()];
1121 keys.sort();
1122 let us_positions: Vec<usize> =
1123 keys.iter().enumerate().filter(|(_, k)| **k == us_a || **k == us_b).map(|(i, _)| i).collect();
1124 assert_eq!(us_positions[1] - us_positions[0], 1, "us partition rows must be contiguous");
1125 }
1126
1127 #[test]
1128 fn test_partition_range_contains_only_its_partition() {
1129 let storage = StorageId::Table(TableId(1));
1130 let range = PartitionedRowKey::partition_range(storage, part("us")).encode();
1131 let us = PartitionedRowKey::encoded(storage, part("us"), RowNumber(500));
1132 let eu = PartitionedRowKey::encoded(storage, part("eu"), RowNumber(1));
1133 assert!(range.contains(&us), "us row must be inside the us partition range");
1134 assert!(!range.contains(&eu), "eu row must be outside the us partition range");
1135 }
1136
1137 #[test]
1138 fn test_partitioned_row_ident_roundtrip() {
1139 let key = PartitionedRowKey {
1140 storage: StorageId::Table(TableId(7)),
1141 partition: part("us"),
1142 row: RowNumber(42),
1143 };
1144
1145 let ident: StoragePartitionedRowKey = key.clone().into();
1147 let restored = ident.with_storage(key.storage);
1148 assert_eq!(restored, key);
1149 }
1150
1151 #[test]
1152 fn test_partitioned_row_ident_halves_split_correctly() {
1153 let partition = Partition(0x1122334455667788_99AABBCCDDEEFF00);
1154 let ident = StoragePartitionedRowKey::new(partition, RowNumber(1));
1155
1156 assert_eq!(ident.partition_hi(), 0x1122334455667788);
1158 assert_eq!(ident.partition_lo(), 0x99AABBCCDDEEFF00);
1159 assert_eq!(ident.partition(), partition);
1160 assert_eq!(
1161 StoragePartitionedRowKey::from_halves(ident.partition_hi(), ident.partition_lo(), RowNumber(1)),
1162 ident
1163 );
1164 }
1165
1166 #[test]
1167 fn test_partitioned_row_ident_ordering_matches_field_order() {
1168 let lower_partition = StoragePartitionedRowKey::new(Partition(1), RowNumber(999));
1169 let higher_partition = StoragePartitionedRowKey::new(Partition(2), RowNumber(1));
1170 let same_partition_lower_row = StoragePartitionedRowKey::new(Partition(2), RowNumber(1));
1171 let same_partition_higher_row = StoragePartitionedRowKey::new(Partition(2), RowNumber(2));
1172
1173 assert!(higher_partition < lower_partition);
1176 assert!(same_partition_higher_row < same_partition_lower_row);
1177 }
1178
1179 #[test]
1180 fn test_partitioned_row_ident_successor_carries_into_the_partition() {
1181 let last_row = StoragePartitionedRowKey::new(Partition(5), RowNumber(0));
1184 let next = last_row.successor().unwrap();
1185
1186 assert_eq!(next, StoragePartitionedRowKey::new(Partition(4), RowNumber(u64::MAX)));
1187 assert!(next > last_row);
1188 }
1189
1190 #[test]
1191 fn test_partitioned_row_ident_low_is_the_greatest_partition_and_row() {
1192 assert_eq!(
1193 <StoragePartitionedRowKey as BoundedKey>::low(),
1194 StoragePartitionedRowKey::new(Partition(u128::MAX), RowNumber(u64::MAX))
1195 );
1196 }
1197
1198 #[test]
1199 fn test_decode_rejects_trailing_bytes() {
1200 let exact = RowKey::encoded(StorageId::table(7), RowNumber(42));
1204 assert_eq!(exact.as_slice().len(), 18);
1205 assert_eq!(
1206 RowKey::decode(&exact),
1207 Some(RowKey {
1208 storage: StorageId::table(7),
1209 row: RowNumber(42)
1210 })
1211 );
1212
1213 let mut longer = exact.as_slice().to_vec();
1214 longer.push(0x00);
1215 assert_eq!(RowKey::decode(&EncodedKey::new(longer)), None);
1216 }
1217
1218 #[test]
1219 fn test_decode_rejects_a_longer_key_that_shares_the_kind_byte() {
1220 let mut sorted_view = RowKey::encoded(StorageId::view(3), RowNumber(1)).as_slice().to_vec();
1224 sorted_view.extend_from_slice(&[0xAA; 8]);
1225 sorted_view.extend_from_slice(&99u64.to_be_bytes());
1226
1227 assert_eq!(RowKey::decode(&EncodedKey::new(sorted_view)), None);
1228 }
1229}
1230
1231#[cfg(test)]
1232mod sorted_view_run_tests {
1233 use reifydb_codec::key::encoded::EncodedKey;
1234 use reifydb_value::value::{partition::Partition, row_number::RowNumber};
1235
1236 use super::{PartitionedSortedViewRowKey, SortRun, SortedViewRowKey};
1237 use crate::interface::catalog::storage::StorageId;
1238
1239 fn run(bytes: &[u8]) -> SortRun {
1240 SortRun::new(bytes)
1241 }
1242
1243 #[test]
1244 fn test_a_run_round_trips_through_the_terminator() {
1245 let key = SortedViewRowKey::new(StorageId::view(3), run(&[0x10, 0x00, 0xff, 0x00]), RowNumber(42));
1248 let decoded = SortedViewRowKey::decode(&key.encode()).unwrap();
1249 assert_eq!(decoded, key);
1250 assert_eq!(decoded.run.as_slice(), &[0x10, 0x00, 0xff, 0x00]);
1251 }
1252
1253 #[test]
1254 fn test_an_empty_run_round_trips() {
1255 let key = SortedViewRowKey::new(StorageId::view(3), run(&[]), RowNumber(1));
1256 assert_eq!(SortedViewRowKey::decode(&key.encode()), Some(key));
1257 }
1258
1259 #[test]
1260 fn test_a_partitioned_run_round_trips() {
1261 let key = PartitionedSortedViewRowKey::new(
1262 StorageId::view(3),
1263 Partition(0x1122334455667788_99AABBCCDDEEFF00),
1264 run(&[0x00, 0x00, 0x01]),
1265 RowNumber(7),
1266 );
1267 assert_eq!(PartitionedSortedViewRowKey::decode(&key.encode()), Some(key));
1268 }
1269
1270 #[test]
1271 fn test_decode_refuses_the_other_kind_and_trailing_bytes() {
1272 let partitioned = PartitionedSortedViewRowKey::encoded(
1274 StorageId::view(3),
1275 Partition(1),
1276 run(&[0x10]),
1277 RowNumber(1),
1278 );
1279 assert_eq!(SortedViewRowKey::decode(&partitioned), None);
1280
1281 let mut longer = SortedViewRowKey::encoded(StorageId::view(3), run(&[0x10]), RowNumber(1)).to_vec();
1282 longer.push(0x00);
1283 assert_eq!(SortedViewRowKey::decode(&EncodedKey::new(longer)), None);
1284 }
1285
1286 #[test]
1287 fn test_ord_matches_the_encoded_byte_order() {
1288 let mut keys = [
1291 SortedViewRowKey::new(StorageId::table(3), run(&[0x10]), RowNumber(1)),
1292 SortedViewRowKey::new(StorageId::view(3), run(&[0x10]), RowNumber(1)),
1293 SortedViewRowKey::new(StorageId::view(4), run(&[0x10]), RowNumber(1)),
1294 SortedViewRowKey::new(StorageId::view(3), run(&[0x10]), RowNumber(2)),
1295 SortedViewRowKey::new(StorageId::view(3), run(&[0x10, 0x00]), RowNumber(0)),
1296 SortedViewRowKey::new(StorageId::view(3), run(&[0x10, 0x01]), RowNumber(0)),
1297 SortedViewRowKey::new(StorageId::view(3), run(&[0x00]), RowNumber(0)),
1298 SortedViewRowKey::new(StorageId::view(3), run(&[]), RowNumber(u64::MAX)),
1299 ];
1300 keys.sort();
1301
1302 let encoded: Vec<EncodedKey> = keys.iter().map(|key| key.encode()).collect();
1303 let mut sorted_bytes = encoded.clone();
1304 sorted_bytes.sort();
1305 assert_eq!(encoded, sorted_bytes);
1306 }
1307
1308 #[test]
1309 fn test_partitioned_ord_matches_the_encoded_byte_order() {
1310 let mut keys = [
1311 PartitionedSortedViewRowKey::new(StorageId::view(3), Partition(1), run(&[0x10]), RowNumber(1)),
1312 PartitionedSortedViewRowKey::new(StorageId::view(3), Partition(2), run(&[0x10]), RowNumber(1)),
1313 PartitionedSortedViewRowKey::new(StorageId::view(3), Partition(2), run(&[0x00]), RowNumber(1)),
1314 PartitionedSortedViewRowKey::new(StorageId::view(3), Partition(2), run(&[0x10]), RowNumber(0)),
1315 PartitionedSortedViewRowKey::new(StorageId::view(4), Partition(2), run(&[0x10]), RowNumber(0)),
1316 ];
1317 keys.sort();
1318
1319 let encoded: Vec<EncodedKey> = keys.iter().map(|key| key.encode()).collect();
1320 let mut sorted_bytes = encoded.clone();
1321 sorted_bytes.sort();
1322 assert_eq!(encoded, sorted_bytes);
1323 }
1324
1325 #[test]
1326 fn test_a_shorter_run_sorts_before_the_run_that_extends_it() {
1327 let short = SortedViewRowKey::new(StorageId::view(3), run(&[0x10]), RowNumber(u64::MAX));
1330 let long = SortedViewRowKey::new(StorageId::view(3), run(&[0x10, 0x00]), RowNumber(0));
1331
1332 assert!(short < long);
1333 assert!(short.encode() < long.encode());
1334 }
1335
1336 #[test]
1337 fn test_the_helpers_still_read_the_new_layout() {
1338 let storage = StorageId::view(3);
1339 let key = SortedViewRowKey::encoded(storage, run(&[0x00, 0xAA]), RowNumber(9));
1340 assert_eq!(SortedViewRowKey::storage_of(&key), Some(storage));
1341 assert_eq!(SortedViewRowKey::row_of(&key), Some(RowNumber(9)));
1342
1343 let partitioned =
1344 PartitionedSortedViewRowKey::encoded(storage, Partition(5), run(&[0x00, 0xAA]), RowNumber(9));
1345 assert_eq!(PartitionedSortedViewRowKey::storage_of(&partitioned), Some(storage));
1346 assert_eq!(PartitionedSortedViewRowKey::row_of(&partitioned), Some(RowNumber(9)));
1347 assert_eq!(SortedViewRowKey::row_of(&partitioned), None);
1348 }
1349}