Skip to main content

reifydb_core/key/
column.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use crate::{
5	encoded::key::{EncodedKey, EncodedKeyRange},
6	interface::catalog::{id::ColumnId, schema::SchemaId},
7	key::{EncodableKey, KeyKind},
8	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
9};
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct ColumnKey {
13	pub object: SchemaId,
14	pub column: ColumnId,
15}
16
17const VERSION: u8 = 1;
18
19impl EncodableKey for ColumnKey {
20	const KIND: KeyKind = KeyKind::Column;
21
22	fn encode(&self) -> EncodedKey {
23		let mut serializer = KeySerializer::with_capacity(19); // 1 + 1 + 9 + 8
24		serializer
25			.extend_u8(VERSION)
26			.extend_u8(Self::KIND as u8)
27			.extend_schema_id(self.object)
28			.extend_u64(self.column);
29		serializer.to_encoded_key()
30	}
31
32	fn decode(key: &EncodedKey) -> Option<Self> {
33		let mut de = KeyDeserializer::from_bytes(key.as_slice());
34
35		let version = de.read_u8().ok()?;
36		if version != VERSION {
37			return None;
38		}
39
40		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
41		if kind != Self::KIND {
42			return None;
43		}
44
45		let object = de.read_schema_id().ok()?;
46		let column = de.read_u64().ok()?;
47
48		Some(Self {
49			object,
50			column: ColumnId(column),
51		})
52	}
53}
54
55impl ColumnKey {
56	pub fn encoded(object: impl Into<SchemaId>, column: impl Into<ColumnId>) -> EncodedKey {
57		Self {
58			object: object.into(),
59			column: column.into(),
60		}
61		.encode()
62	}
63
64	pub fn full_scan(object: impl Into<SchemaId>) -> EncodedKeyRange {
65		let object = object.into();
66		EncodedKeyRange::start_end(Some(Self::start(object)), Some(Self::end(object)))
67	}
68
69	fn start(object: SchemaId) -> EncodedKey {
70		let mut serializer = KeySerializer::with_capacity(11);
71		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_schema_id(object);
72		serializer.to_encoded_key()
73	}
74
75	fn end(object: SchemaId) -> EncodedKey {
76		let mut serializer = KeySerializer::with_capacity(11);
77		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_schema_id(object.prev());
78		serializer.to_encoded_key()
79	}
80}
81
82#[cfg(test)]
83pub mod tests {
84	use super::EncodableKey;
85	use crate::{
86		interface::catalog::{id::ColumnId, schema::SchemaId},
87		key::ColumnKey,
88	};
89
90	#[test]
91	fn test_encode_decode() {
92		let key = ColumnKey {
93			object: SchemaId::table(0xABCD),
94			column: ColumnId(0x123456789ABCDEF0),
95		};
96		let encoded = key.encode();
97
98		let expected: Vec<u8> = vec![
99			0xFE, // version
100			0xF8, // kind
101			0x01, // SchemaId type discriminator (Table)
102			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, // object id bytes
103			0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43, 0x21, 0x0F, // column id bytes
104		];
105
106		assert_eq!(encoded.as_slice(), expected);
107
108		let key = ColumnKey::decode(&encoded).unwrap();
109		assert_eq!(key.object, 0xABCD);
110		assert_eq!(key.column, 0x123456789ABCDEF0);
111	}
112
113	#[test]
114	fn test_order_preserving() {
115		let key1 = ColumnKey {
116			object: SchemaId::table(1),
117			column: ColumnId(100),
118		};
119		let key2 = ColumnKey {
120			object: SchemaId::table(1),
121			column: ColumnId(200),
122		};
123		let key3 = ColumnKey {
124			object: SchemaId::table(2),
125			column: ColumnId(0),
126		};
127
128		let encoded1 = key1.encode();
129		let encoded2 = key2.encode();
130		let encoded3 = key3.encode();
131
132		assert!(encoded3 < encoded2, "ordering not preserved");
133		assert!(encoded2 < encoded1, "ordering not preserved");
134	}
135}