reifydb_catalog/store/dictionary/
list.rs1use reifydb_core::{
5 interface::{DictionaryDef, DictionaryId, NamespaceId, QueryTransaction},
6 key::{DictionaryKey, NamespaceDictionaryKey},
7};
8use reifydb_type::Type;
9
10use crate::{
11 CatalogStore,
12 store::dictionary::layout::{dictionary, dictionary_namespace},
13};
14
15impl CatalogStore {
16 pub async fn list_dictionaries(
18 rx: &mut impl QueryTransaction,
19 namespace: NamespaceId,
20 ) -> crate::Result<Vec<DictionaryDef>> {
21 let batch = rx.range(NamespaceDictionaryKey::full_scan(namespace)).await?;
23 let dictionary_ids: Vec<DictionaryId> = batch
24 .items
25 .iter()
26 .map(|multi| {
27 let row = &multi.values;
28 DictionaryId(dictionary_namespace::LAYOUT.get_u64(row, dictionary_namespace::ID))
29 })
30 .collect();
31
32 let mut dictionaries = Vec::new();
33 for dictionary_id in dictionary_ids {
34 if let Some(dictionary) = Self::find_dictionary(rx, dictionary_id).await? {
35 dictionaries.push(dictionary);
36 }
37 }
38
39 Ok(dictionaries)
40 }
41
42 pub async fn list_all_dictionaries(rx: &mut impl QueryTransaction) -> crate::Result<Vec<DictionaryDef>> {
44 let mut dictionaries = Vec::new();
45
46 let batch = rx.range(DictionaryKey::full_scan()).await?;
47 for multi in batch.items {
48 let row = &multi.values;
49 let id = DictionaryId(dictionary::LAYOUT.get_u64(&row, dictionary::ID));
50 let namespace = NamespaceId(dictionary::LAYOUT.get_u64(&row, dictionary::NAMESPACE));
51 let name = dictionary::LAYOUT.get_utf8(&row, dictionary::NAME).to_string();
52 let value_type_ordinal = dictionary::LAYOUT.get_u8(&row, dictionary::VALUE_TYPE);
53 let id_type_ordinal = dictionary::LAYOUT.get_u8(&row, dictionary::ID_TYPE);
54
55 dictionaries.push(DictionaryDef {
56 id,
57 namespace,
58 name,
59 value_type: Type::from_u8(value_type_ordinal),
60 id_type: Type::from_u8(id_type_ordinal),
61 });
62 }
63
64 Ok(dictionaries)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use reifydb_engine::test_utils::create_test_command_transaction;
71 use reifydb_type::Type;
72
73 use crate::{
74 CatalogStore, namespace::NamespaceToCreate, store::dictionary::create::DictionaryToCreate,
75 test_utils::ensure_test_namespace,
76 };
77
78 #[tokio::test]
79 async fn test_list_dictionaries_empty() {
80 let mut txn = create_test_command_transaction().await;
81 let namespace = ensure_test_namespace(&mut txn).await;
82
83 let result = CatalogStore::list_dictionaries(&mut txn, namespace.id).await.unwrap();
84
85 assert!(result.is_empty());
86 }
87
88 #[tokio::test]
89 async fn test_list_dictionaries_multiple() {
90 let mut txn = create_test_command_transaction().await;
91 let namespace = ensure_test_namespace(&mut txn).await;
92
93 for i in 0..3 {
95 let to_create = DictionaryToCreate {
96 namespace: namespace.id,
97 dictionary: format!("dict_{}", i),
98 value_type: Type::Utf8,
99 id_type: Type::Uint2,
100 fragment: None,
101 };
102 CatalogStore::create_dictionary(&mut txn, to_create).await.unwrap();
103 }
104
105 let result = CatalogStore::list_dictionaries(&mut txn, namespace.id).await.unwrap();
106
107 assert_eq!(result.len(), 3);
108 }
109
110 #[tokio::test]
111 async fn test_list_dictionaries_different_namespaces() {
112 let mut txn = create_test_command_transaction().await;
113 let namespace1 = ensure_test_namespace(&mut txn).await;
114
115 let namespace2 = CatalogStore::create_namespace(
116 &mut txn,
117 NamespaceToCreate {
118 namespace_fragment: None,
119 name: "namespace2".to_string(),
120 },
121 )
122 .await
123 .unwrap();
124
125 for i in 0..2 {
127 let to_create = DictionaryToCreate {
128 namespace: namespace1.id,
129 dictionary: format!("ns1_dict_{}", i),
130 value_type: Type::Utf8,
131 id_type: Type::Uint2,
132 fragment: None,
133 };
134 CatalogStore::create_dictionary(&mut txn, to_create).await.unwrap();
135 }
136
137 for i in 0..3 {
139 let to_create = DictionaryToCreate {
140 namespace: namespace2.id,
141 dictionary: format!("ns2_dict_{}", i),
142 value_type: Type::Uint8,
143 id_type: Type::Uint4,
144 fragment: None,
145 };
146 CatalogStore::create_dictionary(&mut txn, to_create).await.unwrap();
147 }
148
149 let ns1_dicts = CatalogStore::list_dictionaries(&mut txn, namespace1.id).await.unwrap();
151 assert_eq!(ns1_dicts.len(), 2);
152
153 let ns2_dicts = CatalogStore::list_dictionaries(&mut txn, namespace2.id).await.unwrap();
155 assert_eq!(ns2_dicts.len(), 3);
156 }
157
158 #[tokio::test]
159 async fn test_list_all_dictionaries() {
160 let mut txn = create_test_command_transaction().await;
161 let namespace1 = ensure_test_namespace(&mut txn).await;
162
163 let namespace2 = CatalogStore::create_namespace(
164 &mut txn,
165 NamespaceToCreate {
166 namespace_fragment: None,
167 name: "namespace2".to_string(),
168 },
169 )
170 .await
171 .unwrap();
172
173 for i in 0..2 {
175 let to_create = DictionaryToCreate {
176 namespace: namespace1.id,
177 dictionary: format!("ns1_dict_{}", i),
178 value_type: Type::Utf8,
179 id_type: Type::Uint2,
180 fragment: None,
181 };
182 CatalogStore::create_dictionary(&mut txn, to_create).await.unwrap();
183 }
184
185 for i in 0..3 {
186 let to_create = DictionaryToCreate {
187 namespace: namespace2.id,
188 dictionary: format!("ns2_dict_{}", i),
189 value_type: Type::Uint8,
190 id_type: Type::Uint4,
191 fragment: None,
192 };
193 CatalogStore::create_dictionary(&mut txn, to_create).await.unwrap();
194 }
195
196 let all_dicts = CatalogStore::list_all_dictionaries(&mut txn).await.unwrap();
198 assert_eq!(all_dicts.len(), 5);
199 }
200}